#Contents
----
**eeWikiを開発するっす
eeWikiを開発するにあたりTODOというか、日記というか、覚書というか走り書きです。まとまった文書にはならないと思いますが...お許しください。

by J.r0ck
----
***2003.07.02 eeWiki-1.xを目指して
eeWiki-0.1を作ってみていろいろなことを学びました。
コンセプトは、Strutsを使って何かを作ってみるのが、Strutsを知るのに一番早いと思ったことをきっかけに、Strutsを使ったServletコンテナで動く何か...だったら仕様も単純なWikiなんていいんじゃないかな？と。
人の真似だとかいわれたっていいんです。とにかく、作らないと何も始まらない。
で、作ってみると...「あっ、ここもっとこうした方がいいんじゃない？」「へぇー、こうやってるんだ」「こんなこと出来ないかしら？」といろんなことが見えてくるんですね。
これは、お金もらって業務アプリ作ってると絶対に出てこない（自分は）ことなんですね。
そういえば20年くらい前、Z80のマシン語で（アセンブラなんてお金なくて買えなかった）パックマンのクローン作ったのがコンピュータで何かを作った最初だったかな？
#オフィシャルロゴはその頃のことを思い出して、意識的に作ってます。eの字雰囲気あるでしょ。

#Size(3:#Color(blue:今後の構想...))
またまた、真似かっていわれちゃうかもしれないのだけれど、sng氏（PukiWikiの作者）のleafwikiみたいなノード管理できるWikiに1.0以降していきたいと思ってます。
Wikiを使ってWebサイトを構築するとわかってもらえると思うのですが、結構毎回同じことを繰り返さないといけないんですよね。
例えば、いくつかコンテンツがあって「魚」「野菜」「肉」についてそれぞれ語ったページを作っていくとすると、「魚」のリンクからやっぱりわかりやすくしたいので、「魚」についてのINDEX的なページを作ることになるんです。
>ページA「魚」に対するリンク
>ページB「魚」関連に関するリンクのINDEXページ
>ページC「鯛」
>ページD「鮪」
>ページE「鯖」
で、更に、「鯛」について「釣る」「食べる」とか次のINDEXを作らなきゃならない。
#ベタで書いてもいいんですが、やっぱり見る人がわかりずらいでしょ。

すると、そこに見えてくるんです。「あー、同じことを繰り返すのは機械にやらせたいな」って。
だったら、アウトラインプロセッサ風？ノード風？にページを作成していければ自動的にINDEXは作成できちゃうなってことにまりますよね。

#Size(3:#Color(blue:そこで問題...))
ノードの親のページが消されたらどうする？
+そういえば、ページが消せちゃうのがWikiの弱点（悪意をもってすればすべてのページも消せてしまう）
+だったら、いっそページ削除で物理的にファイル削除しなきゃダメ？
+それなら、消したページは拡張子を変更する程度にして、ユーザーからはごみ箱に入ってるような感じにしたら？
+親を消された子ノードは、Adopted child（里子）として里親にリンクするってのは？
うーん、切りなくいろんなアイディアが問題定義に対して浮かんできますね。
----
***2003.07.05 XMLパーサー
Wikiデータにノードの概念を持たせるのであれば、データをXML化してデータ自体に自分の親と子供のポインタ（多分ページIDになると思います）を持たせることになるでしょう。
そこでXMLでWikiデータを扱う場合XMLパーサーなどに何を使うかな？と検討。DOM、SAX、JDOM、JXpathなどいろいろ試してみたのですが、''org.exolab.castor''フレームワークで決まりですね。
XMLのマッピングのためのクラスを作成して
>public class SimpleWiki implements Serializable {
>>private String title = null;
>>private boolean frozen = false;
>>private Date lastmodified = null;
>>private String lastowner = null;
>>private String parents  = null;
>>private HashMap child = null;
>>private HashMap history = null;
>>private String content = null;
>>/**
>> * 
>> */
>>public SimpleWiki() {
>>>super();
>>}
>>/**
>> * @param string
>> */
>>public SimpleWiki(String title) {
>>>this.title = title;
>>}
>>/**
>> * @return
>> */
>>public HashMap getChild() {
>>>return child;
>>}
> .... 後はフィールドのGeter/Seterだけなので省略

>//Create a Reader to the file to unmarshal from	
>FileReader reader = new FileReader("c:\\tmp\\test.xml");
>
>//Marshal the SimpleWiki object
>//XMLファイルの読込み
>SimpleWiki sw = (SimpleWiki)Unmarshaller.unmarshal(SimpleWiki.class, reader);
>	
>//データの設定 Jdomと違い自動で<>'"&はすべて変換はしてくれない
>//自分の環境では、>だけが自動で変換されません。
>//なので、> → ＆ｇｔ；などの置換はセット前に明示的におこなうべし
>sw.setParents("root");
>sw.setContent ("日本語㈱①1～<>\n日本語㈱①～<>\n日本語㈱①～<>\n日本語㈱①～<>\n");
>
>//Create a File to marshal to	
>FileWriter writer = new FileWriter("c:\\tmp\\test.xml");
>
>//XMLファイル出力
>Marshaller.marshal(sw, writer);
データバインディングのコレクションのようなクラスを利用して、こんなに簡単にXMLデータを作成、編集できてしまうんですね。リレーショナルDBのデータを扱うのに似た感じで操作できます。
あとは、JakartaCommonsのJXpathが魅力的なのですが、こちらはまだ調査中です。
----
***2003.07.06 org.exolab.castor XMLフレームワーク
#Size(3:#Color(blue:おーっと))、''org.exolab.castor''はなんとxsdでXMLの構造を定義すると、そのXMLの対してアクセスするためのコレクションのようなクラスを自動生成してくれるじゃないですか！
すごい楽ですね。しかも、validateもスケルトン作成してくれるし。これなら、XMLの構造をしばらくたって変更したくなっても全然OKですよ。
''wiki.xsdの中身''
#ShowText(wiki.xsd.txt)
これで後は...castor-0.9.5-xml.jarとxerces.jarにclasspathを通して
>java org.exolab.castor.builder.SourceGenerator -i wiki.xsd -package org.j69.eewiki.content
とするだけで、
>HistoryItem.java
>HistoryItemDescriptor.java
>HistoryItemList.java
>HistoryItemListDescriptor.java
>NodeItem.java
>NodeItemDescriptor.java
>NodeItemList.java
>NodeItemListDescriptor.java
>Wikidata.java
>WikidataDescriptor.java
といったXMLにアクセスするためのクラスを生成してくれました。

Castorには、DTDでマッピングを書いとく方式もあるけれどeeWiki-1.0はスキーマ形式の方式で行こうと思います。
ただし、自動作成したクラス内を結果的にいじりまわさなければならないとなると話は別...。そうなると、修正個所を変更が入るたびに移植しなければいけなくなります。
----
***2003.07.07 Jakarta Commons JXPath
Jakarta CommonsのJXPathを実際のデータ操作に使用してみる。
Mobsterの縣氏が「Jakartaプロジェクト徹底攻略」って本でCommonsに付いて書いた記事を読みながら、Castorで作成したコレクションを使ってゴニョゴニョ。
>FileReader reader = new FileReader(xmlfilename);
>Wikidata content = (Wikidata)Unmarshaller.unmarshal(Wikidata.class, reader);
>JXPathContext jxpc = JXPathContext.newContext(content);
>String data = (String)jxpc.getValue("historyItemList/historyItem[1]/data");
>System.out.println("data = " + data);
>data = (String)jxpc.getValue("historyItemList/historyItem[2]/data");
>System.out.println("data = " + data);
''historyItemList/historyItem[2]/data''というXPATH形式で間単にデータにアクセスできちゃいます。
XMLDocumentContainerでXMLファイルを直接読み込むこともできますが、今のところファイルに出力する方法がわからないので、とりあえずは''Castor+JXPath''をもう少しいじりまわしてみます。

例えば、ノードの中からある条件に沿ったデータを抽出したいとき
>Address address = null;
>Collection locations = vendor.getLocations();
>Iterator it = locations.iterator();
>while (it.hasNext()){
>>Location location = (Location)it.next();
>>String zipCode = location.getAddress().getZipCode();
>>if (zipCode.equals("90210")){
>>>address = location.getAddress();
>>>break;
>>}
>}
と、こう書かなければならないところを...
>Address address = (Address)JXPathContext.newContext(vendor).
>>getValue("locations[address/zipCode='90210']/address");
こう書けばいいんだから楽だし、なんか素直ですよね。
----
***2003.07.08 ノードの関連付けを複数のクライアントで...
今日、細川氏と雑談していて...ページ間のノードリンク（親子関係）を自由に変更できるとなると、複数の人が同時に以下のようなことをした場合どうなっちゃうのだろうか？
#Color(blue:例)
-ページＡ
--ページＢ
---ページＢ－１
--ページＣ
---ページＣ－１
-ページＤ
...という関連のノードがあったとして、''Ａさん''は、ページＢをＤの子供に変更。
-ページＡ
-ページＤ
--ページＢ
---ページＢ－１
--ページＣ
---ページＣ－１
とリンクを張り替えた。とほぼ同時期に''Ｂさん''は、ページＢ－１をＣの子供に変更。
-ページＡ
--ページＢ
--ページＣ
---ページＢ－１
---ページＣ－１
-ページＤ
とリンクを張り替えた。
''？？？？''結果どうなるのが正しいのかしら？
-ページＡ
-ページＤ
--ページＢ
--ページＣ
---ページＢ－１
---ページＣ－１
これで、いいのかなぁ？

それとか、ネストしたページは？
#Color(blue:例)
-ページＡ
--ページＢ
---ページＣ
だったのを...ページＡの親をページＣにしちゃったら
ネストしちゃいますよね。

#Size(5:#Color(blue:あっ!))全然関係ないけど、こういう長いページのメニューって...意味ないじゃない（涙）
----
***2003.07.10 eeWiki-1.0はこうなる
[[eeWikiはこうなる]]
----
***2003.07.10 Wikiと日本語
[[Wikiと日本語]]について考え始めました...今ごろ？（汗）
----
***2003.07.10 Tomcatアドミン画面のTreeView
Wiki全体のノード構造を直感的に見せるにはやはり、TreeViewを使いたい。Tomcatのアドミン画面ではしっかりTreeViewを使っているのでうまく利用できないだろうか？
今日は、超暇だったのでいろいろ調べてみた結果...
Tree表示には以下のクラスを使用しています。
-TreeBuilder.class
-TreeControl.class
-TreeControlNode.class
-TreeControlTag.class
Jakartaのことだから...「きっとすごく簡単に使えるようになってるに違いない」と何度も自分に言い聞かせてソースを眺めてみます。
すると、
>TreeControlNode root = new TreeControlNode("ROOT-NODE",
>>>null, rootnodeName,
>>>"setUpTree.do?select=ROOT-NODE",
>>>"content", true);
>TreeControl control = new TreeControl(root);
>if(treeBuildersStr != null) {
>>Class treeBuilderImpl;
>>TreeBuilder treeBuilderBase;
>>ArrayList treeBuilders = new ArrayList(INIT_PLUGIN_MAX);
>>int i = 0;
>>StringTokenizer st = new StringTokenizer(treeBuildersStr, ",");
>>while (st.hasMoreTokens()) {
>>>treeBuilders.add(st.nextToken().trim());
>>}
>>if(treeBuilders.size() == 0)
>>>treeBuilders.add(treeBuildersStr.trim());
>>for(i = 0; i < treeBuilders.size(); i++) {
>>try{
>>>treeBuilderImpl = Class.forName((String)treeBuilders.get(i));
>>>treeBuilderBase = (TreeBuilder)treeBuilderImpl.newInstance();
>>>treeBuilderBase.buildTree(control, servlet, request);
>>}catch(Throwable t){
>....
で、Treeを作成し、

>protected void addSubtree(TreeControlNode root,
>>MessageResources resources) {
>>TreeControlNode subtree = new TreeControlNode
>>("Global Resource Administration",
>>"folder_16_pad.gif",
>>resources.getMessage("resources.treeBuilder.subtreeNode"),
>>null,
>>"content",
>>true);
>TreeControlNode datasources = new TreeControlNode
>>("Globally Administer Data Sources",
>>"Datasource.gif",
>>resources.getMessage("resources.treeBuilder.datasources"),
>>"resources/listDataSources.do?resourcetype=Global&forward=" +
>>URLEncoder.encode("DataSources List Setup"),
>>"content",
>>false);
>....
>root.addChild(subtree);
>subtree.addChild(datasources);
>subtree.addChild(mailsessions);
>subtree.addChild(envs);
>subtree.addChild(userdbs);
とかして、Treeを編集しているようです。
うーん、なんか簡単に使えそうに気なってきた...。
しかも、
<%@ taglib uri="/WEB-INF/controls.tld" prefix="controls" %>
だってさ！しっかりStrutsのオリジナルタグまでありますね。
