勉強会記録(2/12)

2月 12th, 2008

オブジェクト指向入門 第2版 原則・コンセプト pp.467-477 (大野, 青木)

  • パートC オブジェクト指向の技法
    • 第11章契約による設計:信頼性の高いソフトウェアを構築する
      • 11.8 クラス不変表明
        • 11.8.1 定義と例
        • 11.8.2 クラス不変表明の形式と特質
        • 11.8.3 変化する不変表明
        • 11.8.4 不変表明を守らなければならないのは誰か?
        • 11.8.5 ソフトウェア工学におけるクラス不変表明規則
        • 11.8.6 不変表明と契約
      • 11.9 クラスが正しいのはいつか?
        • 11.9.1 クラスの正しさ
        • 11.9.2 生成プロシージャの役割

iDotメモ3(データファイルのロード)

2月 8th, 2008

iDot起動または、ツールバーの「Open」ボタンのクリックでファイルのロード処理が起動する。

idot.iDotクラス


/**
* Tries to load the state diagram from the specified file. The file
* is assumed to be in DOT format.
* After the file is loaded, a layout operation (using DOT) is attempted.
*
* @param graphFile
* @return true, if the file was loaded successfully and the laying out
* the graph using DOT completed without errors
*/

protected boolean loadFile(File graphFile) {
  boolean fileLoaded = false;
  try {
    BufferedReader br = new BufferedReader(
                new InputStreamReader(new FileInputStream(graphFile)));
    long size = graphFile.length();
    if(size > 1024*1024)
      throw new IOException(“File too big (> 1 MB): ” + graphFile);
    StringBuilder sb = new StringBuilder((int) size);
    String line;
    do {
      line = br.readLine();
      if(line != null) {
        sb.append(line).append(‘\n’);
      }
    } while(line != null);
    display.setDotFileContents(sb.toString());
    saveFile = graphFile;
    graphState = null;
    if (Config.print)
      System.out.println(“opened ” + graphFile.getName());
      display.runDOTLayout();//①
    updateTitle();
    fileLoaded = true;
  } catch ( Exception ex ) {
    JOptionPane.showMessageDialog(
      display,
      ”Sorry, an error occurred while loading the graph.\n” +
      ”(“+ ex.getLocalizedMessage() + “)”,
      ”Error Loading Graph”,
      JOptionPane.ERROR_MESSAGE);
    ex.printStackTrace();
  }
  return fileLoaded;
}

①idot.DotDisplayクラスのrunDOTLayout()メソッドをコール

idot.DotDisplayクラス

/**
* Tries to perform the layout of the current graph by executing DOT
* with the current graph content (in DOT format) as input.
* If DOT is executed succesfully, the graph is lo9aded
*/

protected void runDOTLayout() {
  Graph g = null;
  try {
    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    ProcessBuilder pb = new ProcessBuilder(dotCommand);//②
    /* If dot gives a lot of warnings the error stream
    * may get full which hangs the program –> have to empty
    * it somehow.
    * Reading it through getErrorStream() would require
    * some extra effort.
    */

    pb.redirectErrorStream(true);
    Process p = pb.start();
    OutputStream os = new BufferedOutputStream(p.getOutputStream());
    InputStream is = new BufferedInputStream(p.getInputStream());
    // pipe graph to dot
    os.write(getDotFileContents().getBytes());
//③
    // dot will only close after getting EOF
    os.close();
    // pipe output to graph layout
    g = dotReader.loadGraph(is);//④
    p.waitFor();
    if(p.exitValue() != 0) {
      System.err.println(“Process ” + dotCommand + ” exited with value ” + p.exitValue());
      throw new IOException(“DOT exit value: ” + p.exitValue());
    }
    setGraph(g);//⑤
  } catch ( Exception ex ) {
    JOptionPane.showMessageDialog(
      this,
      ”Sorry, an error occurred while running DOT.\n” +
      ”(“+ ex.getLocalizedMessage() + “)”,
      ”Error Running DOT”,
      JOptionPane.ERROR_MESSAGE);
    ex.printStackTrace();

    setCursor(Cursor.getDefaultCursor());
  }
}

//**
* Sets the graph shown on this display.
*
* @param g
*/

public void setGraph(Graph g) {
  // update graph
  m_vis.removeGroup(GRAPH_GROUP);
  m_vis.addGraph(GRAPH_GROUP, g);//⑥

  // create data description of labels, setting colors, fonts ahead of time
  Schema edgeLabelSchema = createEdgeLabelSchema();

  m_vis.removeGroup(“edgeLabels”);
  explicitHide((Graph) m_vis.getVisualGroup(GRAPH_GROUP));

  m_vis.addDecorators(“edgeLabels”, GRAPH_EDGES, null, edgeLabelSchema);//⑦

  runFilterUpdate();
  runLayout();//⑧
}

②別プロセスを起動するためProcessBuilderオブジェクトを作成。String配列のdotCommandは{“bin\dot”,”-Tdot”}となっている。
③読み込んだファイルのデータを、別プロセスのアウトプットストリームに書き込む。
この別プロセスでは、nodeの位置決めとedgeの曲線を計算しているようだ。
④idot.util.DotFileReaderクラスのloadGraphメソッドをコールして、prefuse.data.Graphオブジェクトにデータを読み込む。
⑤setGraph()メソッドをコール
⑥prefuse.VisualizationオブジェクトにGraphオブジェクトをGRAPH_GROUPという名前で登録する。
GraphオブジェクトをVisualizationに登録すると自動的にprefuse.visual.VisualGraphオブジェクトが作られる。
VisualGraphオブジェクトは、Graphオブジェクトが持つデータの他、可視化(表示)のために必要な情報(座標、色、サイズなど)を持っている。
⑦edgeのラベル用にDecoratorを登録。Decoratorを登録すると既存のvisual data group(この場合は、GRAPH_EDGESという名前のグループ)に新たなコントロールを追加することができるようになるようだ。具体的には、edgeラベルの表示に使われる。
⑧レイアウトを実行する。レイアウト処理は、idot.DotLayoutクラスに実装されている。

iDotメモ2へ

勉強会記録(2/5)

2月 5th, 2008

オブジェクト指向入門 第2版 原則・コンセプト pp.446-456 (大野, 青木)

  • パートC オブジェクト指向の技法
    • 第11章契約による設計:信頼性の高いソフトウェアを構築する
      • 11.6 ソフトウェア信頼性のための契約
        • 11.6.3 表明は入力検査メカニズムにあらず
        • 11.6.4 表明は制御構造にあらず
        • 11.6.5 エラー、欠陥、その他、モゾモゾ這い回るやつ
      • 11.7 表明を用いた作業
        • 11.7.1 スタッククラス
        • 11.7.2 命令的であることと適用的であること
        • 11.7.3 空(empty)の構造に関する知見

iDotメモ2(idot.DotDisplayクラス)

2月 1st, 2008

idot.DotDisplayクラス

DotDisplayクラスはprefuseグラフィックライブラリのprefuse.Displayクラスを継承している。
prefuse.Displayクラスはprefuse.Visualizationクラスのコンテンツを表示する役割がある。
DotDisplayクラスのコンストラクタはiDotクラスのコンストラクタからコールされる。
DotDisplayクラスのコンストラクタを見てみる。

/**
* Creates a new DotDisplay initialized with the given graph
*
* @param graph
* the graph to load to the display
*/

public DotDisplay(Graph graph) {//①
  this(graph, new Visualization());
}

/**
* Creates a new DotDisplay initialized the given graph and visualization
*
* @param graph
* the graph to load to the display
* @param visualization
* the visualization that will be used provide the visual
* counterparts for the objects in the graph
*/

public DotDisplay(Graph graph, Visualization visualization) {//②
  super();
  setHighQuality(true);//③
  setVisualization(visualization);//④

  // initialize renderers ⑤
  MultilineTextItemRenderer nodeRenderer = new MultilineTextItemRenderer(
                         MultilineTextItemRenderer.CENTER);
  TransitionRenderer edgeRenderer = new TransitionRenderer();
  DefaultRendererFactory rf = new DefaultRendererFactory(nodeRenderer,edgeRenderer);
  rf.add(“INGROUP(‘edgeLabels’)”, new LabelRenderer() {//⑥
    public void render(Graphics2D g, VisualItem item) {

      // make sure edge labels are at correct positions before rendering them
      if (item.canGet(“lp2”, double[].class)) {
        double[] xy = (double[]) item.get(“lp2”);
        if (xy != null) {
          item.setX(xy[0]);
          item.setY(xy[1]);
          super.render(g, item);
        }
      }
    }
  });

  // hide invisible nodes and edges
  rf.add(“style=’invis'”, new NullRenderer());
  m_vis.setRendererFactory(rf);

  // initialize display ⑦
  setBackground(Color.WHITE);
  addControlListeners();//⑧
  addLayouts();//⑨
  setGraph(graph);//⑩
}

iDotクラスのコンストラクタからDotDisplayのコンストラクタ①がコールされる。
コンストラクタ①はコンストラクタ②をコールする。
③レンダリングの品質に関する設定で、falseにすると表示が粗くなる。
④purefuse.Visualizationオブジェクトを設定している。
Visualizationはprefuseグラフィックライブラリの中でも重要なクラスのようだ。
⑤からはレンダラーファクトリ作成処理である。idot.util.MultilineTextItemRendererはノードのレンダラーで、複数行に渡るテキストと枠線を描くクラス。idot.util.TransitionRendererは、ノードとノードをつなぐ線(=edge)を描くクラス。
⑥さらにedgeラベル用のレンダラーをDefaultRendererFactoryに追加している。
DefaultRendererFactory#add(String predicate, Renderer r)のpredicateは、
rのレンダリング対象とするVisualItemを決めるための条件である。
ここでは、’edgeLabels’グループに属するVisualItemという条件。
⑦DefaultRendererFactoryを④で設定したVisualizationに設定する。
⑧コントロールリスナーを追加する
⑨レイアウトを追加する
⑩Graphオブジェクトを設定する。

次に⑧のコントロールリスナー登録メソッド(addControlListeners())を見てみる。
このメソッドでは、VisualizationへのActionListの登録とDotDisplayへのControlの登録をしている。

/**
* Adds the needed control listeners and action lists to the display.
*/

private void addControlListeners() {
  // update takes care of colors and font sizes
  ActionList update = new ActionList(m_vis);
  ColorAction color = new ColorAction(GRAPH_GROUP, VisualItem.STROKECOLOR) {//①
    @Override
    public int getColor(VisualItem item) {
      // honor the value of the color attribute
      if (item.canGetInt(“color”)) {
        return item.getInt(“color”);
      }
    return super.getColor(item);
    }
  };
  // base color is black
  color.setDefaultColor(ColorLib.rgb(0, 0, 0));
  update.add(color);

  // text is always black
  color = new ColorAction(GRAPH_GROUP, VisualItem.TEXTCOLOR);//②
  color.setDefaultColor(ColorLib.gray(0));
  update.add(color);

  // arrow heads are filled with color from the attribute, and nodes with white
  color = new ColorAction(GRAPH_GROUP, VisualItem.FILLCOLOR) {//③
    @Override
    public int getColor(VisualItem item) {
      // honor the value of the color attribute
      if (item instanceof EdgeItem && item.canGetInt(“color”)) {
        return item.getInt(“color”);
      } else if (item instanceof NodeItem
            && item.getString(“shape”).equalsIgnoreCase(“point”)) {
        return item.getStrokeColor();
      }
      return super.getColor(item);
    }
  };

  color.add(“ingroup(‘” + GRAPH_EDGES + “‘)”, ColorLib.gray(0));
  color.setDefaultColor(ColorLib.gray(255));
  update.add(color);

  // hilighted nodes and edges are drawn with doubled lines
  // StrokeAction stroke = new StrokeAction(GRAPH_GROUP);
  // stroke.add(“_highlight”, StrokeLib.getStroke(2));
  // update.add(stroke);

  update.add(new FontAction() {//④
    public Font getFont(VisualItem item) {
      String fontname = currFont.getFamily();
      int fontsize = currFont.getSize();
      if (item.canGetString(“fontname”)) {
        fontname = item.getString(“fontname”);
      }
      if (item.canGetInt(“fontsize”)) {
        fontsize = item.getInt(“fontsize”);
      }
      return FontLib.getFont(fontname, fontsize);
      // return currFont;
    }//
  });

  ShapeDecoder sd = new ShapeDecoder(“shape”);//⑤
  update.add(sd);
  StrokeAction sa = new StrokeAction(GRAPH_GROUP, new BasicStroke());//⑥
  sa.add(“style=’bold'”, new BasicStroke(2));
  // this is alternative to using a NullRenderer, although this is not completely invisible
  // sa.add(“style=’invis'”, new BasicStroke(0));

  update.add(sa);
  update.add(new RepaintAction());
  m_vis.putAction(“update”, update);//⑦
  addControlListener(new ZoomControl());//⑧
  addControlListener(new PanControl());
  addControlListener(new InvertedWheelZoomControl());
  addControlListener(new FocusControl(0));
  Controller c = new Controller();
  controller = c;
  addControlListener(c);
}

①線の色の設定。
itemのcolorフィールドに設定があればその設定値を、なければ黒。
②テキストの色(=黒)の設定。
③矢印のヘッドとノードの内部の色の設定。
itemのcolorフィールドに設定があればその設定値を、なければ矢印のヘッドは黒、ノードの内部は白。
④フォントの設定。
⑤ノードの形の設定。VisualItemのデータフィールド”shape”の値で形が決定することを設定している。
⑥線の太さの設定
⑦これまでの設定を”update”という名前を付けてVisualizationに登録する。
⑧からはコントロールの登録
ZoomControl:ビューア画面上のマウス右ボタンドラッグで拡大縮小
PanControl:背景のマウス左ボタンドラッグで全体が移動
InvertedWheelZoomControl:マウスホイールの回転で拡大縮小
FocusControl:ノードやエッジ(矢印)へのカーソルのフォーカスイベントで起動するコントローラ
Controller:専用コントローラ。DotDisplayのインナークラスで定義
Controllerクラスでは、イベント発生時の処理をしている。主な機能は次のとおり。

  • nodeのダブルクリックで子ノードを表示する
  • nodeまたはedgeのドラッグ

iDotメモ1へ  iDotメモ3へ

iDotメモ1

1月 25th, 2008

iDot Version 1.0メモ

http://stwww.weizmann.ac.il/g-cs/benari/idot/index.html

上記ホームページの情報から、iDotとは
Graphviz言語で記述された方向があるグラフを表示するためのビューアで、
機能は、次のとおり。

  • ノードのダブルクリックでそのノードと直接関係するノードが表示できる
  • ノードとエッジ(ノード間の矢印)のドラッグアンドドロップによるレイアウト変更
  • キャンバス上でのマウス左クリックによるパン
  • キャンバス上でのマウス右クリックによるズーム(マウスホイールでも操作可)

動作環境
Java Runtime Environment 1.5以上
prefuseグラフィックライブラリを使用

ライセンスは「GNU General Public License」。
ソースコードが公開されているので中身を見てみる。
まずはmainメソッドがあるクラスidot.iDotから開始。

package idot;
….
  /**
  * State Diagram Visualizer application. This program reads state diagrams
  * produced by the SpinSpider tool and saved in the dot format and displays the
  * diagram interactively to the user, who can then perform different “filters”
  * on the diagram to gain deeper understanding of the operation of the
  * illustrated program or algorithm.
  *
  * Originally based on a sample graph editor in the * href=”http://prefuse.org”>prefuse library made by * href=”http://jheer.org”>Jeffrey Heer.
  */

  public class iDot extends JFrame {

….

  /**
  * Entry point of the program. If there are no command line parameters, an
  * empty application window is opened. If there are command line parameters,
  * they are considered to be names of files containing state diagrams to be
  * loaded by the application. Every specified file will be opened in a
  * separate window.
  *
  * @param argv
  * the command line parameters
  */

  public static void main(String argv[]) {
    if (argv.length > 0)
      for (String filename : argv)
        new iDot().loadFile(new File(filename));
      else
      new iDot();
  }

….

}

iDotクラスは、javax.swing.JFrameクラスを継承している。
mainメソッドでiDotオブジェクトを作成する。ファイル名が渡されればファイルを読み込む。複数のファイルパスを引数に受け取るとファイルの数だけピューアが起動する。
次にコンストラクタ。

/**
* Default constructor. Will initialize the view with an empty graph.
*/

public iDot() {
  this(new Graph(true), null);//なぜだろう?
}

/**
* A constructor specifying the graph to load to the program.
*
* @param graph
* the graph to be loaded initially
* @param originOfGraph
* an optional string providing additional information about the
* graph to be shown in the title bar of the program
*/

public iDot(Graph graph, String originOfGraph) {
  super();
  setLookAndFeel();
  fileChooser = new JFileChooser(INITIAL_PATH);//①
  fileChooser.addChoosableFileFilter(new ExtensionFileFilter(“.dot”,”*.dot (DOT files)”));
  MenuController controller = new MenuController();
  JToolBar toolBar = new JToolBar();
  display = new DotDisplay(graph);//②
  graphState = originOfGraph;
  updateTitle();
  initToolBar(toolBar, controller);//③
  JPanel contentPane = new JPanel();
  contentPane.setLayout(new java.awt.BorderLayout());
  contentPane.add(toolBar, java.awt.BorderLayout.NORTH);//④
  contentPane.add(display, java.awt.BorderLayout.CENTER);//⑤
  setContentPane(contentPane);
  setDefaultCloseOperation(EXIT_ON_CLOSE);
  setFont(font);
  setSize(WIDTH, HEIGHT);
  setLocationRelativeTo(null);
  setVisible(true);
}

デフォルトコンストラクタは、引数付のコンストラクタをコールする。
ここで、Graphクラスが登場するが、これはprefuseライブラリのクラスprefuse.data.Graphで表示するデータを表している。この段階では表示するデータがないのでGraphオブジェクトは不要だと思うが、なぜか作成している。
コンストラクタでは、
①JFileChooserオブジェクトを作成し、メンバに設定
②DotDisplayオブジェクトを作成し、メンバに設定
③ツールバー作成、初期化
④JPanelオブジェクトにツールバーを登録
⑤JPanelオブジェクトにディスプレイを追加

iDotメモ2へ

勉強会記録(12/21)

12月 21st, 2007

オブジェクト指向入門 第2版 原則・コンセプト pp.331-343 (沼田, 青木)

  • パートC オブジェクト指向の技法
    • 第8章 実行時の構造:オブジェクト
      • 8.7 複合オブジェクトと拡張型
        • 8.7.4 集約
        • 8.7.5 拡張性の性質
        • 8.7.6 サブオブジェクトへの参照はだめ
      • 8.8 アッタチメント:参照と値の意味
        • 8.8.1 アッタチメント
        • 8.8.2 参照とコピーのアタッチメント
        • 8.8.3 ハイブリッドアタッチメント
        • 8.8.4 一致比較
      • 8.9 参照を扱うということ:利点と危険
        • 8.9.1 動的別名付け
        • 8.9.2 別名の意味

勉強会記録(12/4)

12月 4th, 2007

オブジェクト指向入門 第2版 原則・コンセプト pp.269-282 ( 今井、大野、青木)

  • パートC オブジェクト指向の技法
    • 第7章 静的な構造:クラス
      • 7.10 検討
        • 7.10.7 インポートを列挙する
        • 7.10.8 ファンクションの結果の表記
        • 7.10.9 補足:エンティティの厳密な定義
      • 7.11 本章のまとめ
      • 7.12 参考文献
    • 第8章 実行時の構造:オブジェクト
      • 8.1 オブジェクト
        • 8.1.1 オブジェクトとは何か?

忘年会

11月 21st, 2007

忘年会は、タイ料理を予約しました。

http://www.westindia-group.com/muangthai/index.php

とりあえず「タイスキ3,200円コース+飲み放題」で予約しました。

コースの希望などあればコメントください。