プログラマメモ2 - programmer no memo2

目次

H2 Database - CREATE DOMAINが使える 2008/05/28

H2 Database です。


ドキュメントみるとCREATE DOMAINが使えるようです。
えーと、CREATE DOMAINを使う理由は、テーブルごとに制約の設定がちらばることが防げるといったところでしょうか。たぶんこれが実用的な説明なのかも(postgresの説明であった。CREATE DOMAIN)。

あと、CREATE DOMAINが何かしらの型を強制するものであるならいいのかなぁとか考えたり。

参考

H2 Database - MERGE INTOが使える 2008/05/24

SQLについてあまり知らないので、よく悩むのは、レコードがなければinsert、あればupdateと処理するとき。
まずselectして調べて、手続き型言語(SQLを操作する方の側)で、if~else~するっていうのしか思いつかなかったのだけど、oracle 9iというものは、どうもMERGEというものが使えるらしい。

参考



それで、このMERGEって何気に、H2 Databaseで、使えることがわかって、得した気分。
upsert = (update or insert)ってことなのでしょうかね。
対象の行はユニークになる行でないとだめなようです。

Updates the row if it exists, and if the row does not exist, inserts a new row.
If the key columns are not specified, the primary key columns are used to find the row.
This command is sometimes called 'UPSERT' as it updates a row if it exists,
or inserts the row if it does not yet exist.
If more than one row per new row is affected, an exception is thrown.H2 Database Engine

。で終わる行 - .*。$ 2008/05/24

メモ。正規表現。

。で終わる行

.*。$


参考
パズルがたくさん
正規表現パズル

H2 Database - グラフィックなデータを格納してみる。 2008/05/22
2008/09/27

Javaです。
データベースにイメージを格納します。

動機


シナリオ
画像を公開されているwebAPIから取得します。同じ画像を何度も、取得すると提供API側に負荷がかかります。
取得した画像をキャッシュするようにしてください。


というわけで、H2を使って、メモリ上にもたせてみる手習いです。
H2でなければいけないというわけではもちろんないです。

byteの配列を格納します。
その際に、ステートメントのsetBinaryStreamを使っています。
setBytesを使ってもいいようです。

参考

package h2test;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

static class ImageUtils {
public static byte[] getImageBytes(BufferedImage image,
String imageFormat) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
BufferedOutputStream os = new BufferedOutputStream(bos);
image.flush();
ImageIO.write(image, imageFormat, os);
os.flush();
os.close();
return bos.toByteArray();
}
}

public static void main(String[] args) throws SQLException,
ClassNotFoundException, IOException {

// 格納用の画像を作成
BufferedImage bufferedImage = new BufferedImage(200, 200,
BufferedImage.TYPE_INT_ARGB);
{
Graphics2D g2d = (Graphics2D) bufferedImage.createGraphics();
g2d.setColor(new Color(24, 65, 199, 30));

g2d.fillRect(0, 0, 200, 200);
g2d.dispose();
}

Test test = new Test();

test.init();

test.update("INSERT INTO imagetable ( id, image ) VALUES(?, ?)",
"1234", ImageUtils.getImageBytes(bufferedImage, "png"));

Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {

connection = test.getConnection();
statement = connection.createStatement();
resultSet = statement
.executeQuery("select id, image from imagetable");
if (resultSet.next()) {
String id = resultSet.getString("id");
Object o = resultSet.getBinaryStream("image");

try {
final BufferedImage image = ImageIO
.read((ByteArrayInputStream) o);

Thread thread = new Thread(new Runnable() {
public void run() {

JPanel p = new JPanel() {

protected void paintChildren(Graphics g) {

g.drawImage(image, 0, 0, null);

}

};
JFrame frame = new JFrame();
frame

.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(p);
frame.setVisible(true);
}
});
thread.start();
} catch (IOException e) {
e.printStackTrace();
}

}
System.out.println();

} catch (SQLException e) {
e.printStackTrace();
} finally {
Test.close(resultSet, statement, connection);
}
}

protected void init() throws SQLException, ClassNotFoundException {
update("CREATE TABLE imagetable ( id VARCHAR (64) NOT NULL,image BLOB)");
}

protected void update(String expression, Object... param)
throws SQLException, ClassNotFoundException {

Connection connection = getConnection();
PreparedStatement st = null;

st = connection.prepareStatement(expression);

int pos = 1;
for (Object o : param) {
if (o instanceof byte[]) {
byte[] bs = (byte[]) o;
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
bs);
st.setBinaryStream(pos, byteArrayInputStream, bs.length);
continue;
}

st.setObject(pos, o);

pos++;
}

int i = st.executeUpdate(); // run the query

if (i == -1) {
System.err.println("update failed....");
}

st.close();

connection.close();
}

protected void update(String expression) throws SQLException,
ClassNotFoundException {

Connection connection = getConnection();
Statement st = null;

st = connection.createStatement(); // statements

int i = st.executeUpdate(expression); // run the query

if (i == -1) {
System.err.println("update failed....");
}

System.out.println("====>" + i);

st.close();

connection.close();
}

// BasicDataSource dataSource = new BasicDataSource();
// {
// dataSource.setUrl("jdbc:h2:mem:mydb");
// dataSource.setUsername("sa");
// dataSource.setPassword("");
// }

protected Connection getConnection() throws SQLException,
ClassNotFoundException {
Connection connection = null;
try {
Class.forName("org.h2.Driver");
connection = DriverManager.getConnection("jdbc:h2:mem:mydb;DB_CLOSE_DELAY=-1",
"sa",
"");
} catch (SQLException e) {
throw e;
} catch (ClassNotFoundException e) {
throw e;
}

return connection;
}

static void close(ResultSet resultSet, Statement statement,
Connection connection) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
}
}

if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
}
}

if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
}
}
}
}

PerspectiveTransformを使ってみる - 台形変形に向けて 2008/05/18

Javaです。
どうも、アファイン変換を使って台形に変形できないようなので、いろいろさがしていたら、JAI( Java Advanced Imaging)にPerspectiveTransformというクラスがありそれを使うと台形に変形できました。




かくかくしていてあまりできがよくないですが...



package pers;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.image.BufferedImage;
import java.awt.image.renderable.ParameterBlock;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.media.jai.JAI;
import javax.media.jai.PerspectiveTransform;
import javax.media.jai.PlanarImage;
import javax.media.jai.RenderedOp;
import javax.media.jai.WarpPerspective;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test4_PerspectiveTransform {

static class Panel extends JPanel {

@Override
protected void paintComponent(Graphics g) {

Graphics2D g2d = (Graphics2D) g;
p(g2d);

}

void p(Graphics2D g2d) {

try {
BufferedImage image = c();
g2d.drawImage(image, 30, 20, null);
g2d.drawImage(a(image), 30 + image.getWidth() + 10, 20, null);
} catch (IOException e) {
e.printStackTrace();
} catch (NoninvertibleTransformException e) {
e.printStackTrace();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}

}

/**
* イメージを読み込みます。
* @return
* @throws IOException
*/
static BufferedImage c() throws IOException {
BufferedImage src = ImageIO.read(Test4_PerspectiveTransform.class
.getResource("z.jpg"));
// ※背景を透明にするらめにわざわざ描き直しています。
// 他にいい方法はないのか?
BufferedImage image = new BufferedImage(src.getWidth(), src.getHeight(),
BufferedImage.TYPE_INT_ARGB_PRE);
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.drawImage(src, 0, 0, null);

return image;
}

public static void main(String[] args) {

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Panel());
frame.setSize(500, 250);
frame.setVisible(true);

}

/**
* 台形にします。
* @param image
* @return
* @throws NoninvertibleTransformException
* @throws CloneNotSupportedException
*/
public static BufferedImage a(BufferedImage image)
throws NoninvertibleTransformException, CloneNotSupportedException {

int w = image.getWidth();
int h = image.getHeight();
PerspectiveTransform transform = PerspectiveTransform.getQuadToQuad(0,
0, w, 0, w, h, 0, h, 0, 0, w, 30, w, h - 30, 0, h
);

ParameterBlock pb = new ParameterBlock();

pb.addSource(image);
pb.add(new WarpPerspective(transform.createInverse()));

RenderedOp renderedOp = JAI.create("warp", pb);

PlanarImage planarImage = renderedOp.createInstance();

return planarImage.getAsBufferedImage();
}
}

下に見える箱、一点透視図法 2008/05/17

目の高さ(アイレベル)が上のときに場合の一点透視です。
消失点が上にきます。




Javaです。
下記コード
package pers;

import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

static class Panel extends JPanel {

@Override
protected void paintComponent(Graphics g) {

Graphics2D g2d = (Graphics2D) g;
// vanishing point
Point vp = new Point(0, 100);
int w = 100;
int h = 100;

int x = 500;
int y = 500;

float dash[] = { 10.0f, 3.0f };
BasicStroke dashStroke = new BasicStroke(1.0f,
BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 3.0f, dash,
0.0f);
BasicStroke stroke = new BasicStroke(1.f);
g2d.setStroke(stroke);
g2d.drawRect(x, y, w, h);
g2d.setStroke(dashStroke);

g2d.drawLine(vp.x, vp.y, x, y);
g2d.drawLine(vp.x, vp.y, x + w, y + h);
g2d.drawLine(vp.x, vp.y, x + w, y);
g2d.drawLine(vp.x, vp.y, x, y + h);

}

}

public static void main(String[] args) {

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Panel());
frame.setVisible(true);

}

}

ドメインモデル貧血症を読んでちょっと考えたこと その2 2008/05/17

メモ



賢いデータは必要なのか (arclamp.jp アークランプ)のコメントでのやりとりが興味深いです。

関連
プログラマメモ2: ドメインモデル貧血症を読んでちょっと考えたこと

JavaからJRubyメソッドに引数をわたしてみる。 2008/05/15

JavaからJRubyで定義したメソッドを呼び出します。
引数渡して結果をもらうことをしてみます。

下記の参考サイトを見よう見まねで試してみました。

参考



目指すはDSLですかね。

ここでは、rubyスクリプトを作ってevalしてますが、これがファイルならファイルを読み込んでevalすればよいわけですね。

ところでどこにjavadocあるんでしょうかね?
調べたいのは、RubyRuntimeAdapter,JavaEmbedUtils,JavaUtil,IRubyObject
とりあえずこれらのクラスは調べておいたほうがよいでしょう。

import java.util.ArrayList;
import org.jruby.Ruby;
import org.jruby.RubyRuntimeAdapter;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.javasupport.JavaUtil;
import org.jruby.runtime.builtin.IRubyObject;
public class Ttt {
public static void main(String[] args) throws Exception {
// jrubyに必要なlibへのパスを指定する?
Ruby ruby = JavaEmbedUtils.initialize(new ArrayList<String>());
// evalするぞ
RubyRuntimeAdapter evaler = JavaEmbedUtils.newRuntimeAdapter();
final String LS = System.getProperty("line.separator");
String script = "def hi(f)" + LS + " return 'i am ' + f " + LS + "end";

// evalします。
IRubyObject robj = evaler.eval(ruby, script);
// IRubyObject eval = evaler.eval(ruby, "hi");
// 引数用意
IRubyObject param = JavaUtil.convertJavaToRuby(ruby, "o_o!");

// 結果
IRubyObject eval = robj.callMethod(ruby.getCurrentContext(), "hi",
param);
System.out.println(eval);
}
}

ネタ Ruby + Groovyって? 2008/05/15

Ruby + Groovyって?

grubyとか思って、検索かけると、
gRuby Project
がでてきました。

他には、gruvyか、gruuvyとかgroobyとか。
無理ありますね。

BufferedImageをバイトの配列にする。 2008/05/15

Javaです。BufferedImageから、byte[]にします。
そのときに、指定されたフォーマットで変換することができます。

オリジナルは、[ヅラド] Java の画像オブジェクト BufferedImage を バイナリ表現 byte[] へ変換する

何故バイトの配列にしたいかといいますと、データベースにBLOBで格納したいからなのでした。

static class ImageUtils {
public static byte[] getImageBytes(BufferedImage image,
String imageFormat) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
BufferedOutputStream os = new BufferedOutputStream(bos);
image.flush();
ImageIO.write(image, imageFormat, os);
os.flush();
os.close();
return bos.toByteArray();
}
}

H2 Database - メモリオンリーデータベースでは、デフォルトでcloseするとデータがなくなる!? 2008/05/14

H2 データベースをインメモリで使う場合、デフォルトでは、closeするとその時点でデータがなくなってしまうようです。
この動作を変更する場合は、接続時のパラメータ(url)にDB_CLOSE_DELAY=-1を設定するといいようです。



以下、サンプルコード

protected Connection getConnection() throws SQLException,
ClassNotFoundException {
Connection connection = null;
try {
Class.forName("org.h2.Driver");
connection = DriverManager.getConnection("jdbc:h2:mem:mydb;DB_CLOSE_DELAY=-1",
"sa",
"");
} catch (SQLException e) {
throw e;
} catch (ClassNotFoundException e) {
throw e;
}

return connection;
}

del.icio.usで最近ブックマークしたものを可視化してみる。 2008/05/11
2008/05/11

はじめに


ここ数日間やってたことのまとめです。
del.icio.usで最近ブックマークしたものを日付ごとで、表示します。その時に、ブックマークした記事をsimpleapiでサムネイル化したものを取得して、アイソメトリックな感じで表示します。

日付ごとでどれだけブックマークされた記事が多いかわかりやすくなったかな。

結果、こんな感じ。



実装


描画するまでは何となくできたのですが、これを並べ替えたり、操作するのってもう少し練らないと。
はじめから3Dを使うというアプローチのほうがよいのかな。

基本は四角のものをBufferedImageにして、つぎに、それをAffineTransformで、shearします。
それを重ねて描画します。その時に、描画する位置を、計算。下記のユーティリティメソッド使ってます。

package d;

import java.awt.Point;

public class IsometricUtils {

/**
* 中心位置から指定された角度の点を求めます。
* @param degree 角度
* @param cx 中心位置
* @param cy 中心位置
* @param R 距離
* @return
*/
static public Point point(double degree, int cx, int cy, int R) {
int x = (int) (cx + (R * Math.sin(Math.toRadians(degree))));
int y = (int) (cy + (R * Math.cos(Math.toRadians(degree))));
return new Point(x, y);
}

}


あと、del.icio.us apiの決まり事で、

Please wait AT LEAST ONE SECOND between queries, or you are likely to get automatically throttled. If you are releasing a library to access the API, you MUST do this.

クエリーの間隔をあけないといけないみたいなんだけど、ばこすかアクセスしてたせいなのかしらないけど、途中で、エラーがでて、壱時間ぐらいアクセスできなくなったので、注意すべし。

以下、とりあえず、コード。長いけど。
package d;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.AreaAveragingScaleFilter;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

import org.apache.http.HttpException;
import org.xml.sax.SAXException;

import d.DeliciousUtils.Post;

public class Test {

public static void main(String[] args) throws Exception {
a();
}

static void a() throws IOException, HttpException, InterruptedException,
URISyntaxException, XPathExpressionException, SAXException,
ParserConfigurationException {

final List<BufferedImage> list1 = c("username", "password");

System.out.println(list1);
JFrame frame = new JFrame();
class P extends JPanel {

@Override
protected void paintChildren(Graphics g) {
Graphics2D g2d = (Graphics2D) g;

if (!(0 < list1.size()))
return;

Point P = new Point(10, 10);

Point p2 = new Point(P.x, list1.get(0).getHeight());
for (BufferedImage image : list1) {
// int yy = p2.y - image.getHeight();
g2d.drawImage(image, P.x, P.y, null);
P = IsometricUtils.point(60, P.x, P.y, 70);

}

}

}
P p = new P();
p.setBackground(Color.black);
frame.getContentPane().add(p);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 500);
frame.setVisible(true);

}

/**
* サイズの大きいイメージに大きさをあわせてイメージをつくりなおします。
*
* @param list
* @return
*/
static List<BufferedImage> d(List<BufferedImage> list) {
int w = 0;
int h = 0;
for (BufferedImage image : list) {
System.out.println(image);
w = w < image.getWidth() ? image.getWidth() : w;
h = h < image.getHeight() ? image.getHeight() : h;
}

List<BufferedImage> list2 = new ArrayList<BufferedImage>();
for (BufferedImage image : list) {
BufferedImage image2 = new BufferedImage(w, h,
BufferedImage.TYPE_INT_ARGB);
int x = w - image.getWidth();
int y = (h - image.getHeight());

image2.createGraphics().drawImage(image, x, 0, null);

System.out.println("x:" + x + " y:" + y);
list2.add(image2);
}

return list2;
}

/**
* おおまかなロジックの流れ<br>
* (1)デリシャアスから最近のブックマークをとってきます。<br>
* (2)日付順で記事を分けます<br>
* (3)simpleapiを使って画像を取得します。<br>
* (4)表示のために空のイメージを足したりする<br>
*
* @param username
* @param passowrd
* @return
* @throws IOException
* @throws HttpException
* @throws InterruptedException
* @throws URISyntaxException
* @throws XPathExpressionException
* @throws SAXException
* @throws ParserConfigurationException
*/
static List<BufferedImage> c(String username, String passowrd)
throws IOException, HttpException, InterruptedException,
URISyntaxException, XPathExpressionException, SAXException,
ParserConfigurationException {
String sxml = DeliciousUtils.recent(username, passowrd);
if (sxml == null)
return null;
// System.out.println(sxml);
List<Post> posts = DeliciousUtils.toPosts(sxml);
if (!(0 < posts.size()))
return null;
final List<BufferedImage> list = new ArrayList<BufferedImage>();
Map<Integer, List<Post>> map = new TreeMap<Integer, List<Post>>();

for (Post post : posts) {
Integer t = getTime_yyyyMMdd(post.time);
if (!map.containsKey(t)) {
List<Post> list2 = new ArrayList<Post>();
list2.add(post);
map.put(t, list2);
continue;
}

map.get(t).add(post);
}

// 揃えて表示させるための処理(よくない)
int max = 0;
Iterator<List<Post>> it = map.values().iterator();
while (it.hasNext()) {
List<d.DeliciousUtils.Post> list3 = (List<d.DeliciousUtils.Post>) it
.next();
max = (max < list3.size()) ? list3.size() : max;
}

System.out.println(map);
List<BufferedImage> list2 = new ArrayList<BufferedImage>();
Iterator<Integer> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
Integer key = iterator.next();
List<d.DeliciousUtils.Post> list3 = (List<d.DeliciousUtils.Post>) map
.get(key);
Iterator<DeliciousUtils.Post> iterator2 = list3.iterator();

List<BufferedImage> list4 = new ArrayList<BufferedImage>();
while (iterator2.hasNext()) {
DeliciousUtils.Post post = (DeliciousUtils.Post) iterator2
.next();
list4.add(simpleapi(post.href));
}
// 揃えて表示させるための処理(よくない)
for (int i = list4.size(); i < max; i++) {
// 空のイメージを追加
list4.add(0, new BufferedImage(50, 50,
BufferedImage.TYPE_INT_ARGB));
}

list4.add(imageDate("" + key));
// 日付単位のイメージ
list2.add(create1(list4));
}
// System.out.println(list2);
return list2;
}

/**
* Listで受け取ったイメージを一枚一枚づつshearして、並べて一枚のBufferedImageにします。
*
* @param list
* @return
*/
static BufferedImage create1(List<BufferedImage> list) {
final AffineTransform affineTransform = new AffineTransform();

affineTransform.shear(0, Math.toRadians(30));
affineTransform.scale(.82602, 1);
// affineTransform.scale(.3, .3);

final AffineTransformOp op = new AffineTransformOp(affineTransform,
AffineTransformOp.TYPE_BICUBIC);

final List<Image> list2 = new ArrayList<Image>();

final int W = 53;
final int H = 92;
for (BufferedImage image : list) {

image = op.filter(image, null);
ImageFilter filter = new AreaAveragingScaleFilter(W, H);
ImageProducer im = new FilteredImageSource(image.getSource(),
filter);
Image newImage = Toolkit.getDefaultToolkit().createImage(im);
list2.add(newImage);
}

int w = W + (list2.size() * 10);
int h = H + (list2.size() * 10);

BufferedImage b = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2D = (Graphics2D) b.getGraphics();
g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

int x = w - W;
int y = 0;

// System.out.println(w + " " + h);
g2D.setBackground(Color.LIGHT_GRAY);

for (Image image : list2) {
Point point = IsometricUtils.point(-60, x, y, 10);
g2D.drawImage(image, point.x, point.y, null);
x = point.x;
y = point.y;
}
g2D.dispose();
return b;
}

/**
* simpleapiを使ってイメージを取得
*
* @param href
* @return
*/
static BufferedImage simpleapi(String href) {
try {
return ImageIO.read(new URL("http://img.simpleapi.net/small/"
+ href));
} catch (Exception e) {
System.out.println(e);
}
return null;
}

/**
* 比較しやすいように年月日を取得します。
*
* @param time
* @return
*/
public static int getTime_yyyyMMdd(String time) {

try {
Date date = new SimpleDateFormat("yyyy-MM-dd").parse(time);
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
return Integer.parseInt(format.format(date));
} catch (ParseException e) {
e.printStackTrace();
}
return 0;
}

/**
* 日付を書いたプレートをつくる。
* @param sdate
* @return
*/
static BufferedImage imageDate(String sdate) {
BufferedImage b = new BufferedImage(128, 128,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = b.createGraphics();
g2d.setColor(Color.LIGHT_GRAY);
g2d.fillRect(0, 95, 128, 48);
g2d.setColor(Color.ORANGE);
g2d.fillRect(4, 95, 120, 48);
g2d.setColor(Color.BLACK);
g2d.setFont(new Font("", Font.BOLD, 20));
g2d.drawString(sdate, 5, 120);
g2d.dispose();
return b;
}
}

アイソメトリックな表現のための手習い 2008/05/10



アイソメトリックな表現のための実験です。

package d;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test2 {

public static void main(String[] args) {

final Image image = rec(0);
final Image image2 = rec(1);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JPanel() {
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Point P = new Point(300, 100);
for (int j = 0; j < 10; j++) {

Point point = new Point(P.x, P.y);

for (int i = 0; i < 10; i++) {
int cx = point.x;
int cy = point.y;
point = point(-60, point.x, point.y, 10);
// g2d.drawString("" + i, point.x, point.y);
g2d.drawImage(i == 9 ? image : image2, cx, cy, null);

}
int px = P.x;
int py = P.y;
P = point(60, P.x, P.y, 50);
g2d.drawLine(px, py, P.x, P.y);
}

}
});
frame.setSize(500, 500);
frame.setVisible(true);
}

static BufferedImage rec(int pos) {

BufferedImage b = new BufferedImage(30, 50, BufferedImage.TYPE_INT_ARGB);

Graphics2D g2d = b.createGraphics();
g2d.setColor(pos == 0 ? Color.WHITE : Color.LIGHT_GRAY);
g2d.fillRect(0, 0, 30, 50);
g2d.setColor(Color.BLUE);
g2d.drawRect(0, 0, 29, 49);

final AffineTransform affineTransform = new AffineTransform();
affineTransform.shear(0, Math.toRadians(30));
affineTransform.scale(.82602, 1);

final AffineTransformOp op = new AffineTransformOp(affineTransform,
AffineTransformOp.TYPE_BICUBIC);

return op.filter(b, null);
}

static public Point point(double degree, int cx, int cy, int R) {

int x = (int) (cx + (R * Math.sin(Math.toRadians(degree))));
int y = (int) (cy + (R * Math.cos(Math.toRadians(degree))));
return new Point(x, y);
}
}

表現方法を模索中 - AffineTransformを使ってみる。simpleapiも使ってみる。その2 2008/05/10

はじめに


いろいろな方法で情報を表現することを模索中。



simpleapiを使ってみます。
ウェブサイト画面をキャプチャしてサムネイルにしてくれます。すばらしいwebサービスです。

それで、ウェブサイトのサムネイルを並べて表示してみようという試みです。

それで、deliciousからブックマークをとってきて、simpleapiでサムネイルをとってきて


それで、deliciousからブックマークをとってきて、simpleapiでサムネイルをとってきて、並べています。



並べるときに、 等角投影を意識して、えーと、奥行きがある感じを意識しています。全然、厳密ではないです。
simpleapiで取得したサムネイルをshearしています。

影でもつければ、もっといいかもしれません。

以前、作成した、del.icio.usからブックマークをとってくるコードを使っています。


以下、コードです。

package d;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

import org.apache.http.HttpException;
import org.xml.sax.SAXException;

import d.DeliciousUtils.Post;

public class Test {

public static void main(String[] args) throws Exception {
a();
}

static void a() throws IOException, HttpException, InterruptedException,
URISyntaxException, XPathExpressionException, SAXException,
ParserConfigurationException {
String sxml = DeliciousUtils.get("username", "password",
"20080508");
// System.out.println(sxml);
List<Post> posts = DeliciousUtils.toPosts(sxml);

final List<BufferedImage> list = new ArrayList<BufferedImage>();
for (Post post : posts) {
list.add(simpleapi(post.href));
}

// System.out.println(list);

final AffineTransform affineTransform = new AffineTransform();
affineTransform.scale(.82602, 1);
affineTransform.shear(0, Math.toRadians(30));

final AffineTransformOp op = new AffineTransformOp(affineTransform,
AffineTransformOp.TYPE_BICUBIC);



JFrame frame = new JFrame();
class P extends JPanel {

@Override
protected void paintChildren(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
int x = list.size() * 23;
int y = 50;

for (BufferedImage image : list) {
x -= 20;
y += 20;

g2d.drawImage(op.filter(image, null), x, y, null);
}

}

}
P p = new P();
frame.getContentPane().add(p);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);

}

static BufferedImage simpleapi(String href) {
try {
return ImageIO.read(new URL("http://img.simpleapi.net/small/"
+ href));
} catch (Exception e) {
System.out.println(e);
}
return null;
}

}

表現方法を模索中 - AffineTransformを使ってみる。 2008/05/08

動機


情報の可視化で、何かいい感じの表現ができないか模索。

以前から気になっていた表現方法をJavaでできないかちょっと試してみました。

どういうことかといいますと、下記のようなべた2Dなのですが、これを奥行きがあるように表現するって感じです。


下記のような感じにしたい。

適当にイラストレーターで作ったので、ちょっと変ですが...
ニュアンスが伝わるかどうか不安です。

専門的には、何というのでしょうか。

Patent Draftsmen: 斜視図と透視図
投影図 - Wikipedia
等角投影法なんて書き方忘れたよ。 (トモログ)

結果


AffineTransformを使ってみました。
shearというメソッドを使ってます。
[ 1 shx 0 ]
[ shy 1 0 ]
[ 0 0 1 ]

この辺よくわかってないので、要勉強です。



以下、コード
package affinetransform;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class Test {

public static void main(String[] args) throws IOException {
a();
}

static void a() throws IOException{

final BufferedImage image = ImageIO.read(Test.class.getResource("a.png"));
final AffineTransform affineTransform = new AffineTransform();

affineTransform.shear(0, .5);

class P extends JPanel {

@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
g2d.drawImage(image, affineTransform, null);

}

}

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new P());
frame.setVisible(true);

}

}

wikipedia apiを使ってみたい。- JGraphで表示 その3 2008/05/07



表示を少し変えてみました。

package util;

import static util.WikipedialabUtils.getThesaurusDS4NetworkView;
import static util.WikipedialabUtils.getTopCandidateIDFromKeyword;

import java.awt.Color;
import java.awt.Point;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

import org.jgraph.JGraph;
import org.jgraph.graph.DefaultCellViewFactory;
import org.jgraph.graph.DefaultEdge;
import org.jgraph.graph.DefaultGraphCell;
import org.jgraph.graph.DefaultGraphModel;
import org.jgraph.graph.GraphConstants;
import org.jgraph.graph.GraphModel;
import org.xml.sax.SAXException;

import util.WikipedialabUtils.MNode;

public class TestT {

static JGraph graph() {
GraphModel model = new DefaultGraphModel();
JGraph graph = new JGraph(model);

graph.getGraphLayoutCache().setFactory(new DefaultCellViewFactory());
graph.setCloneable(true);
graph.setInvokesStopCellEditing(true);

graph.setJumpToDefaultPort(true);
return graph;
}

static DefaultGraphCell createDefaultGraphCell(String name, int px, int py, int w, int h, Color color){
DefaultGraphCell cell = new DefaultGraphCell(name);

GraphConstants.setBounds(cell.getAttributes(),
new Rectangle2D.Double(px,py,w,h));
GraphConstants.setGradientColor(cell.getAttributes(), color);
GraphConstants.setOpaque(cell.getAttributes(), true);

cell.addPort();
return cell;
}

static Point[] points(int n, final int cx, final int cy, final int R) {
final double d = 360.;
final double d2 = d / n;

Point[] points = new Point[n];
for (int i = 0; i < n; i++) {
int x = (int) (cx + (R * Math.sin(Math.toRadians((d2 * i)))));
int y = (int) (cy + (R * Math.cos(Math.toRadians((d2 * i)))));
points[i] = new Point(x, y);
}
return points;
}

static void c(JGraph graph, MNode parent, DefaultGraphCell cellParent, int cx, int cy, int R, List<DefaultGraphCell> list, Color color) {

int n = parent.child.size();

Collection<MNode> collection = parent.child.values();


list.add(cellParent);
int i = 0;
Point[] points = points(n, cx, cy, R);
Point[] points2 = points(n, cx, cy, R + 100);
for (MNode node : collection) {
Point point = points[i];
DefaultGraphCell cell = createDefaultGraphCell(node.name, point.x, point.y, 80, 20, color);

Point point2 = points2[i];
c(graph, node, cell, point2.x, point2.y, R - 100, list, Color.lightGray);

list.add(cell);

DefaultEdge edge = new DefaultEdge();
edge.setSource(cellParent.getChildAt(0));
edge.setTarget(cell.getChildAt(0));

int arrow = GraphConstants.ARROW_NONE;
GraphConstants.setLineEnd(edge.getAttributes(), arrow);
GraphConstants.setEndFill(edge.getAttributes(), true);

list.add(edge);
i++;
}

}

static void e(JGraph graph, MNode parent){
int cx = 500;
int cy = 500;

int R = 150;
List<DefaultGraphCell> list = new ArrayList<DefaultGraphCell>();
DefaultGraphCell cellParent = createDefaultGraphCell(parent.name, cx, cy, 80, 20, Color.orange);
c(graph, parent, cellParent, cx, cy, R, list, Color.orange);
graph.getGraphLayoutCache().insert(list.toArray());
}

public static void main(String[] args) throws UnsupportedEncodingException, XPathExpressionException, SAXException, IOException, ParserConfigurationException {
JGraph graph = graph();

String skey = "apple";

int i = getTopCandidateIDFromKeyword(WikipedialabUtils.JAPANESE, skey);
String s = getThesaurusDS4NetworkView(WikipedialabUtils.JAPANESE, i);

MNode node = WikipedialabUtils.createDS4NetworkView(skey, i, s);

e(graph, node);

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(graph));
frame.pack();
frame.setVisible(true);
}
}

wikipedia apiを使ってみたい。- JGraphで表示 その2 2008/05/04






表示をかえてみました。対象語を中心に、関連後が円上にひろがってさらにそこから、ひろがった語から、関連する語がひろがるっという感じかな。

GetThesaurusDS4NetworkViewを使っています。


package util;

import static util.WikipedialabUtils.getThesaurusDS4NetworkView;
import static util.WikipedialabUtils.getTopCandidateIDFromKeyword;

import java.awt.Color;
import java.awt.Point;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

import org.jgraph.JGraph;
import org.jgraph.graph.DefaultCellViewFactory;
import org.jgraph.graph.DefaultEdge;
import org.jgraph.graph.DefaultGraphCell;
import org.jgraph.graph.DefaultGraphModel;
import org.jgraph.graph.GraphConstants;
import org.jgraph.graph.GraphModel;
import org.xml.sax.SAXException;

import util.WikipedialabUtils.MNode;

public class TestT {

static JGraph graph() {
GraphModel model = new DefaultGraphModel();
JGraph graph = new JGraph(model);

graph.getGraphLayoutCache().setFactory(new DefaultCellViewFactory());

// Control-drag should clone selection
graph.setCloneable(true);

// Enable edit without final RETURN keystroke
graph.setInvokesStopCellEditing(true);

// When over a cell, jump to its default port (we only have one, anyway)
graph.setJumpToDefaultPort(true);
return graph;
}

static DefaultGraphCell createDefaultGraphCell(String name, int px, int py, int w, int h, Color color){
DefaultGraphCell cell = new DefaultGraphCell(name);

GraphConstants.setBounds(cell.getAttributes(),
new Rectangle2D.Double(px,py,w,h));
GraphConstants.setGradientColor(cell.getAttributes(), color);
GraphConstants.setOpaque(cell.getAttributes(), true);

cell.addPort();
return cell;
}

static Point[] points(int n, final int cx, final int cy, final int R) {
final double d = 360.;
final double d2 = d / n;

Point[] points = new Point[n];
for (int i = 0; i < n; i++) {
int x = (int) (cx + (R * Math.sin(Math.toRadians((d2 * i)))));
int y = (int) (cy + (R * Math.cos(Math.toRadians((d2 * i)))));
points[i] = new Point(x, y);
}
return points;
}

static void c(JGraph graph, MNode parent, DefaultGraphCell cellParent, int cx, int cy, int R, List<DefaultGraphCell> list, Color color) {

int n = parent.child.size();

Collection<MNode> collection = parent.child.values();


list.add(cellParent);
int i = 0;
Point[] points = points(n, cx, cy, R);
for (MNode node : collection) {
Point point = points[i++];
DefaultGraphCell cell = createDefaultGraphCell(node.name, point.x, point.y, 80, 20, color);

c(graph, node, cell, point.x, point.y, R - 100, list, Color.lightGray);

list.add(cell);

DefaultEdge edge = new DefaultEdge();
edge.setSource(cellParent.getChildAt(0));
edge.setTarget(cell.getChildAt(0));

int arrow = GraphConstants.ARROW_NONE;
GraphConstants.setLineEnd(edge.getAttributes(), arrow);
GraphConstants.setEndFill(edge.getAttributes(), true);

list.add(edge);
}




}

static void e(JGraph graph, MNode parent){
int cx = 500;
int cy = 500;

int R = 200;
List<DefaultGraphCell> list = new ArrayList<DefaultGraphCell>();
DefaultGraphCell cellParent = createDefaultGraphCell(parent.name, cx, cy, 80, 20, Color.orange);
c(graph, parent, cellParent, cx, cy, R, list, Color.orange);
graph.getGraphLayoutCache().insert(list.toArray());
}

public static void main(String[] args) throws UnsupportedEncodingException, XPathExpressionException, SAXException, IOException, ParserConfigurationException {
JGraph graph = graph();

String skey = "apple";

int i = getTopCandidateIDFromKeyword(WikipedialabUtils.JAPANESE, skey);
String s = getThesaurusDS4NetworkView(WikipedialabUtils.JAPANESE, i);

MNode node = WikipedialabUtils.createDS4NetworkView(skey, i, s);

e(graph, node);

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(graph));
frame.pack();
frame.setVisible(true);
}
}

wikipedia apiを使ってみたい。- JGraphで表示 2008/05/04



なんとなく可視化に挑戦。
中心におかれた語の関連後を周りに配置しています。

メインページ - Wikipedia-Lab
wikipedia-labのapiを使っています。

前、記事を書いたものをベースにしています。
プログラマメモ2: wikipedia apiを使ってみたい。- Java + axis2

表示するために使ったライブラリは、
Java Graph Visualization and Layout

package util;

import static util.WikipedialabUtils.getThesaurusDS4NetworkView;
import static util.WikipedialabUtils.getTopCandidateIDFromKeyword;

import java.awt.Color;
import java.awt.Point;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

import org.jgraph.JGraph;
import org.jgraph.graph.DefaultCellViewFactory;
import org.jgraph.graph.DefaultEdge;
import org.jgraph.graph.DefaultGraphCell;
import org.jgraph.graph.DefaultGraphModel;
import org.jgraph.graph.GraphConstants;
import org.jgraph.graph.GraphModel;
import org.xml.sax.SAXException;

import util.WikipedialabUtils.MNode;

public class TestT {

static JGraph graph() {
GraphModel model = new DefaultGraphModel();
JGraph graph = new JGraph(model);

graph.getGraphLayoutCache().setFactory(new DefaultCellViewFactory());

// Control-drag should clone selection
graph.setCloneable(true);

// Enable edit without final RETURN keystroke
graph.setInvokesStopCellEditing(true);

// When over a cell, jump to its default port (we only have one, anyway)
graph.setJumpToDefaultPort(true);
return graph;
}

static DefaultGraphCell createDefaultGraphCell(String name, int px, int py, int w, int h){
DefaultGraphCell cell = new DefaultGraphCell(name);

GraphConstants.setBounds(cell.getAttributes(),
new Rectangle2D.Double(px,py,w,h));
GraphConstants.setGradientColor(cell.getAttributes(), Color.orange);
GraphConstants.setOpaque(cell.getAttributes(), true);

cell.addPort();
return cell;
}

static Point[] points(int n, final int cx, final int cy, final int R) {
final double d = 360.;
final double d2 = d / n;

Point[] points = new Point[n];
for (int i = 0; i < n; i++) {
int x = (int) (cx + (R * Math.sin(Math.toRadians((d2 * i)))));
int y = (int) (cy + (R * Math.cos(Math.toRadians((d2 * i)))));
points[i] = new Point(x, y);
}
return points;
}

static void c(JGraph graph, MNode parent) {

int n = parent.child.size();

int cx = 200;
int cy = 200;

int R = 200;

List<DefaultGraphCell> list = new ArrayList<DefaultGraphCell>();
Collection<MNode> collection = parent.child.values();

DefaultGraphCell cellParent = createDefaultGraphCell(parent.name, cx, cy, 80, 20);
list.add(cellParent);
int i = 0;
Point[] points = points(n, cx, cy, R);
for (MNode node : collection) {
Point point = points[i++];
DefaultGraphCell cell = createDefaultGraphCell(node.name, point.x, point.y, 80, 20);


list.add(cell);

DefaultEdge edge = new DefaultEdge();
edge.setSource(cellParent.getChildAt(0));
edge.setTarget(cell.getChildAt(0));

int arrow = GraphConstants.ARROW_NONE;
GraphConstants.setLineEnd(edge.getAttributes(), arrow);
GraphConstants.setEndFill(edge.getAttributes(), true);

list.add(edge);
}


graph.getGraphLayoutCache().insert(list.toArray());

}

public static void main(String[] args) throws UnsupportedEncodingException, XPathExpressionException, SAXException, IOException, ParserConfigurationException {
JGraph graph = graph();

String skey = "apple";

int i = getTopCandidateIDFromKeyword(WikipedialabUtils.JAPANESE, skey);
String s = getThesaurusDS4NetworkView(WikipedialabUtils.JAPANESE, i);

MNode node = WikipedialabUtils.createDS4NetworkView(skey, i, s);

c(graph, node);

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(graph));
frame.pack();
frame.setVisible(true);
}
}


wikipedia apiからデータを取得する部分
package util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.axis2.databinding.types.UnsignedInt;
import org.tempuri.ServiceStub;
import org.tempuri.ServiceStub.GetThesaurusDS;
import org.tempuri.ServiceStub.GetThesaurusDS300;
import org.tempuri.ServiceStub.GetThesaurusDS300Response;
import org.tempuri.ServiceStub.GetThesaurusDS4NetworkView;
import org.tempuri.ServiceStub.GetThesaurusDS4NetworkViewResponse;
import org.tempuri.ServiceStub.GetThesaurusDSResponse;
import org.tempuri.ServiceStub.GetTopCandidateIDFromKeyword;
import org.tempuri.ServiceStub.GetTopCandidateIDFromKeywordResponse;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public abstract class WikipedialabUtils {

static public final String JAPANESE = "Japanese";

static int getTopCandidateIDFromKeyword(String lang, String skeyword)
throws RemoteException {
ServiceStub serviceStub = new ServiceStub();

GetTopCandidateIDFromKeyword keyword = new GetTopCandidateIDFromKeyword();
keyword.setKeyword(skeyword);
keyword.setLanguage(lang);

GetTopCandidateIDFromKeywordResponse response = serviceStub
.GetTopCandidateIDFromKeyword(keyword);

return response.getGetTopCandidateIDFromKeywordResult().intValue();
}

static String getThesaurusDS(String lang, int i) throws RemoteException {

ServiceStub serviceStub = new ServiceStub();

GetThesaurusDS getThesaurusDS = new GetThesaurusDS();
getThesaurusDS.setLanguage(lang);
getThesaurusDS.setIFrom(new UnsignedInt(i));

GetThesaurusDSResponse response = serviceStub
.GetThesaurusDS(getThesaurusDS);

return "" + response.getGetThesaurusDSResult().getExtraElement();
}

static String getThesaurusDS300(String lang, int i) throws RemoteException {

ServiceStub serviceStub = new ServiceStub();

GetThesaurusDS300 getThesaurusDS300 = new GetThesaurusDS300();
getThesaurusDS300.setLanguage(lang);
getThesaurusDS300.setIFrom(new UnsignedInt(i));

GetThesaurusDS300Response response = serviceStub
.GetThesaurusDS300(getThesaurusDS300);

return "" + response.getGetThesaurusDS300Result().getExtraElement();
}

static String getThesaurusDS4NetworkView(String lang, int i)
throws RemoteException {

ServiceStub serviceStub = new ServiceStub();

GetThesaurusDS4NetworkView getThesaurusDS4NetworkView = new GetThesaurusDS4NetworkView();
getThesaurusDS4NetworkView.setLanguage(lang);
getThesaurusDS4NetworkView.setIFrom(new UnsignedInt(i));

GetThesaurusDS4NetworkViewResponse response = serviceStub
.GetThesaurusDS4NetworkView(getThesaurusDS4NetworkView);

return ""
+ response.getGetThesaurusDS4NetworkViewResult()
.getExtraElement();
}

static MNode createDS4NetworkView(String name, int n, String sxml)
throws UnsupportedEncodingException, SAXException, IOException,
ParserConfigurationException, XPathExpressionException {
Document document = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().parse(
new ByteArrayInputStream(sxml.getBytes("utf-8")));
List<Table> list = new ArrayList<Table>();
XPath path = XPathFactory.newInstance().newXPath();

NodeList nodeList = (NodeList) path.evaluate("/diffgram/NewDataSet",
document, XPathConstants.NODESET);

MNode parent = new MNode(name, n);

for (int i = 0; i < nodeList.getLength(); i++) {

Node node = nodeList.item(i);
NodeList nodeList2 = node.getChildNodes();

NodeList o = (NodeList)path.evaluate("Center", nodeList2, XPathConstants.NODESET);
for (int j = 0; j < o.getLength(); j++) {
Node node2 = o.item(j);

MNode mn = new MNode();
mn.n = new Integer(path.evaluate("l_to", node2));
mn.name = path.evaluate("name", node2);
mn.weight = new Double(path.evaluate("l_weight", node2));
mn.parent = parent;
parent.add(mn);
}

NodeList o2 = (NodeList)path.evaluate("*[local-name()!='Center']", nodeList2, XPathConstants.NODESET);
for (int j = 0; j < o2.getLength(); j++) {
Node node2 = o2.item(j);
MNode mn = new MNode();
int from = new Integer(path.evaluate("l_from", node2));
mn.n = new Integer(path.evaluate("l_to", node2));
mn.name = path.evaluate("name", node2);
mn.weight = new Double(path.evaluate("l_weight", node2));

MNode p = parent.child(from);
if(p != null){
mn.parent = p;
p.add(mn);
} else {
System.err.println("error parent[" + from + "] not exist.");
}
}

}

return parent;
}

static class Table {

int l_from;
int l_to;
double l_weight;
String name;

public String toString() {
return "l_from:[" + l_from + "] l_to:[" + l_to + "] l_weight:["
+ l_weight + "] name:[" + name + "]";
}
}

static class MNode {
String name;
int n;
double weight;
MNode parent;
Map<Integer, MNode> child = new HashMap<Integer, MNode>();

public MNode(){

}
public MNode(String name, int n){
this.name = name;
this.n = n;
}
public void add(MNode node){
child.put(node.n, node);
}
public MNode child(int n){
return child.get(n);
}

public boolean equals(Object o) {
if (o == null)
return false;
if (!(o instanceof MNode))
return false;
MNode node = (MNode) o;
if (node.n == node.n)
return true;
return false;
}

public String toString(){
return "name:[" + name + "] n:[" + n + "] parent:["
+ (parent != null ? parent.n : -1) + "]";
}

public String toString(int c){
StringBuilder sb = new StringBuilder();
for(int i=0;i<(c*2);i++){
sb.append(" ");
}
sb.append(toString()).append("\n");

Collection<MNode> collection = child.values();
for (MNode node : collection) {
sb.append(node.toString(c + 1));
}
return new String(sb);
}
}

}

XPath エレメント名が〜でないものを取得 2008/05/03

XPathを使って、エレメント名が〜でないものを取得します。
どういうことかといいますと、


<root>
<a>a1</a>
<b1>b1</b1>
<b2>b2</b2>
<b3>b3</b3>
</root>

上記のような構造のXML文書があった場合なのですが、aというエレメント名でないエレメントを取得したい場合にどうXPathを書けばいいか、考えて、ある集合から単純にaではないという集合(NodeSet)を求めればいいだろうという、結論に達したのでした。たいしたことではありませんが....

というわけで下記のようなXPathで取得できます。
*[local-name()!='a']


このlocal-name関数は、ノード集合関数であり、なにやらエレメント名を返してくれる関数のようです。

ちなみに、用語は正確に使いたいのですが、いまいちよくわかってないのが、XML。
お仕事では毎日のようにみているXMLなのですが、正確に説明しようとすると、自信がないです。
エレメント名という言い方をしました、タグとかいってしまっていいのかどうかとか...

参考

wikipedia apiを使ってみたい。- Java + axis2 2008/05/01

動機


Wikipediaシソーラス - Wikipedia-Labがちょっとおもしろいと思ったので、ちょっと実験。

このWikipedia-LabのWikipediaシソーラスは、リンク構造に着目したWikipediaマイニングから開発されているそうです。


Wikipediaシソーラスビジュアライザー - Wikipedia-Labがかっこよかったです。

Javaです。WSDLをaxis2でjavaソースにします。



紹介されているサンプルが.netのものしかなかったのですが(20080502現在)、axis2を使って、wsdlからjavaコードにして、使ってみます。


変換するためにbin/wsdl2javaを使います。
src/org/tempuri/ServiceCallbackHandler.java
src/org/tempuri/ServiceStub.java

が生成されます。

以下、キーワードから、シソーラスを取り出すための簡単なコードです。
まず、GetTopCandidateIDFromKeywordで、番号をidをゲットして、それを使いGetThesaurusDSをゲットするという感じの流れです。

このコードではxmlを単純に標準出力しています。
package org.tempuri;

import java.rmi.RemoteException;

import org.apache.axis2.databinding.ADBException;
import org.apache.axis2.databinding.types.UnsignedInt;
import org.tempuri.ServiceStub.GetThesaurusDS;
import org.tempuri.ServiceStub.GetThesaurusDSResponse;
import org.tempuri.ServiceStub.GetTopCandidateIDFromKeyword;
import org.tempuri.ServiceStub.GetTopCandidateIDFromKeywordResponse;

public class Test {

public static void main(String[] args) throws RemoteException, ADBException {

String[] keywords = { "侍", "apple", "google", "o_o!" };
for (String k : keywords) {
System.out.println(b(a(k)));
}
}

static int a(String skeyword) throws RemoteException {
ServiceStub serviceStub = new ServiceStub();

GetTopCandidateIDFromKeyword keyword = new GetTopCandidateIDFromKeyword();
keyword.setKeyword(skeyword);
keyword.setLanguage("Japanese");

GetTopCandidateIDFromKeywordResponse response = serviceStub
.GetTopCandidateIDFromKeyword(keyword);

return response.getGetTopCandidateIDFromKeywordResult().intValue();
}

static String b(int i) throws RemoteException {

ServiceStub serviceStub = new ServiceStub();

GetThesaurusDS getThesaurusDS = new GetThesaurusDS();
getThesaurusDS.setLanguage("Japanese");
getThesaurusDS.setIFrom(new UnsignedInt(i));

GetThesaurusDSResponse response = serviceStub
.GetThesaurusDS(getThesaurusDS);

return "" + response.localGetThesaurusDSResult.localExtraElement;
}

}

ドメインモデル貧血症を読んでちょっと考えたこと 2008/04/30

ドメインのロジックをドメインオブジェクトの中に入れないという設計ルールに従っているのでしょう。その代わり、すべてのドメインロジックを含むサービスオブジェクト群が存在しているのです。 こういったサービスはドメインモデルの上位に居座り、データのためだけにドメインモデルを使うのです。Martin Fowler's Bliki in Japanese - ドメインモデル貧血症


上記のあとの文章で、
このアンチパターンが根本的に怖いのは、オブジェクト指向設計の基本概念(データと処理を一緒にする)の真逆だということです。ドメインモデル貧血症とは、単なる手続き型設計のことなのです。まさに、私(そしてEric)のようなオブジェクト信望者が、Smalltalkの初期からずーーーーーっと戦ってきたもの、そのものなのです。さらに困ったことに、貧血オブジェクト(Anemic Object) が本物のオブジェクトだと思っているひとがたくさんいます。つまり、オブジェクト指向設計が何たるかをまったく分かっていないということなんです。Martin Fowler's Bliki in Japanese - ドメインモデル貧血症

と続きます。

そうなんです。僕は「オブジェクト指向設計が何たるかをまったく分かっていない」です。

もちろん、別に教科書的な説明を知らないわけではなく(多分)、僕の知識のはもちろんあやういですけども、実感としてオブジェクトが手触りみたいなものが感じられなくなったといいますでしょうか、なんというか。

データベースがあって値を、オブジェクトにつめこんでるだけにしかみえない瞬間があるんですよね。
結局は、オブジェクトの中で整理されて(階層に分けられて)データが入ってて、そのオブジェクトをさらに別のオブジェクトにあてこむだけといいますか。

左から右にデータをバケツリレーのようにオブジェクトに詰め替えてるだけだけのような気がする瞬間があるんです。するとこのバケツリレーのバケツからバケツに移し替えるところにロジックがあるだけという感覚になるんですよね。

うーん、勉強不足、経験不足なんですかね...道を誤ったか...Otz...