Apcoordinator ユーザーズガイド
目次 前ページ次ページ

付録A サンプルアプリケーション

A.2 画面部品のサンプル

■アプリケーションの概要

画面部品を利用して、データを表形式で表示・入力します。 概要モードでは、表を使用しています。
概要モード
詳細モードでは、リストと複合Beanを使用しています。
詳細モード

■アプリケーションの骨格部分

アプリケーションの骨格部分は、付録A.1を参照してください。ここでは簡単な説明にとどめます。
・main.jsp

<HTML>
<HEAD>
<TITLE>model</TITLE>
<%@ page contentType= "text/html; charset=shift_jis" %>
<%@ taglib uri="uji-taglib" prefix="uji" %>
</HEAD>
<BODY>
<uji:dispatch />
<uji:include pane="body" />
</BODY>
</HTML>

領域はbodyひとつだけを使用しています。
・MeisaiBean.java

package model;

public class MeisaiBean extends com.fujitsu.uji.DataBean
{
    protected DataManager dm;

    protected String denpyoNo;
    protected String chumonDate;
    protected String shohinCode;
    protected String shohinName;
    protected String shohinCount;
    protected String tantoOffice;
    protected String nonyuDate;
    protected String kokyakuWard;
    protected String kokyakuName;
    protected String kokyakuPhone;

    public MeisaiBean(DataManager dm, String[] data) {
        this.dm = dm;
        denpyoNo = data[0];
        chumonDate = data[1];
        shohinCode = data[2];
        shohinName = data[3];
        shohinCount = data[4];
        tantoOffice = data[5];
        nonyuDate = data[6];
        kokyakuWard = data[7];
        kokyakuName = data[8];
        kokyakuPhone = data[9];
    }

    public String getDenpyoNo() {
        return denpyoNo;
    }
    public String getChumonDate() {
        return chumonDate;
    }
    public String getShohinCode() {
        return shohinCode;
    }
    public String getShohinName() {
        return shohinName;
    }
    public String getShohinCount() {
        return shohinCount;
    }
    public String getTantoOffice() {
        return tantoOffice;
    }
    public String getNonyuDate() {
        return nonyuDate;
    }
    public String getKokyakuWard() {
        return kokyakuWard;
    }
    public String getKokyakuName() {
        return kokyakuName;
    }
    public String getKokyakuPhone() {
        return kokyakuPhone;
    }

    public void setNonyuDate(String nonyuDate) {
        if(this.nonyuDate != nonyuDate) {
            dm.setNonyuDate(this, nonyuDate);
        }
    }
}

一件のデータを表すデータBeanです。更新はDataManagerクラスを呼び出すことで実行します。また、更新対象でないプロパティのsetメソッドは省略しています。
・DataManager.java

package model;
import java.util.Vector;

public class DataManager {
    Vector data;

    public DataManager() {
    }

    public int getDataCount() {
        return data.size();
    }

    public MeisaiBean getData(int index) {
        return (MeisaiBean)data.elementAt(index);
    }

    public void setNonyuDate(MeisaiBean bean, String value) {
        // データベースの更新処理に相当
        bean.nonyuDate = value;
    }

    public void prepareData() {
        // データベースの読み込み処理に相当
        data = new Vector();
        for(int i = 0; i < initialData.length; i++) {
            MeisaiBean bean = new MeisaiBean(this, initialData[i]);
            data.addElement(bean);
        }
    }

    private static final String initialData[][] = {
        { "401791","20000214","AC106W","エアコン 100V 6畳用ホワイト","1",
            "川崎支店","未定","川崎市中原区","田村電気","044-999-9999" },
        ....(省略)....
    };
}

データのアクセスを提供するクラスです。 このサンプルでは、初期値を文字列で持っています。また更新時もメモリ上のデータを書き換えるだけです。
・ModelBean.java

package model;

public class ModelBean extends com.fujitsu.uji.DataBean
{
    protected SummaryModel summary;
    protected DetailModel detail;

    public SummaryModel getSummary() {
        return summary;
    }

    public DetailModel getDetail() {
        return detail;
    }

    public void initData(DataManager dm) {
        summary = new SummaryModel(dm);
        detail = new DetailModel(dm);
    }
}

データBeanです。summaryとdetailのプロパティがそれぞれ画面部品のインタフェースを提供します。これらのクラスの詳細は後述します。
・ModelHandler.java

package model;
import com.fujitsu.uji.DispatchContext;

public class ModelHandler extends com.fujitsu.uji.GenericHandler
{
    protected DataManager dm;

    public ModelHandler() {
    }
    public boolean init() {
        return true;
    }

    public void showDetail(DispatchContext context, ModelBean dataBean) {
        dataBean.setVerb("detail");
        context.setResponseBean("body", dataBean);
    }

    public void showSummary(DispatchContext context, ModelBean dataBean) {
        dataBean.setVerb("summary");
        context.setResponseBean("body", dataBean);
    }

    public void startup(DispatchContext context) {
        dm = new DataManager();
        dm.prepareData();
        ModelBean dataBean = new ModelBean();
        dataBean.initData(dm);
        dataBean.setVerb("summary");
        context.setResponseBean("body", dataBean);
    }
}

showDetailとshowSummaryでは、表示モードを切り替える(setVerb)のみの処理をしています。 startupメソッドでは、データの初期化をして、概要モードで表示しています。
・commands.map

# commands.map
model.ModelBean;showDetail=model.ModelHandler.showDetail
model.ModelBean;showSummary=model.ModelHandler.showSummary
;=model.ModelHandler.startup

・pages.map

# pages.map
model.ModelBean;summary=summary.jsp
model.ModelBean;detail=detail.jsp

・web.xml
付録A.1と同じです。割愛します。

■概要表示(表の画面部品を使用)

・summary.jsp

<%@ page contentType="text/html; charset=shift_jis" %>
<%@ taglib uri="uji-taglib" prefix="uji" %>
<uji:useBean id="body" cls="model.ModelBean" request="true" />
<P>納入予定日設定(概要モード)</P>
<uji:peTextMode/>
<FORM method="post">
    <INPUT name="uji.verbs" type="hidden" value="showDetail"> 
    <INPUT name="uji.id" type="hidden" value="body">

    <uji:table bean="body" property="summary">
        <uji:tableRenderer type="table" >
            <TABLE border="2" width="100%"><uji:children/></TABLE>
        </uji:tableRenderer>
        <uji:tableRenderer type="column" cls="header" >
            <TH bgcolor="#EEFFEE"><uji:value/></TH>
        </uji:tableRenderer>
        <uji:tableRenderer type="column" cls="editable" >
            <TD><INPUT name="<uji:name/>" value="<uji:value/>"></TD>
        </uji:tableRenderer>
    </uji:table>

    <INPUT name="showDetail" type="submit" value="詳細表示"> 
</FORM>

この入出力ページでは、uji:tableタグを使用しています。 uji:tableタグのアトリビュートでは、TableModelインタフェースを返すプロパティ名としてsummaryを指定しています。 uji:tableの中ではレンダラとして3つのuji:tableRendererタグを指定しています。レンダラは表やセルのフォーマットを記述するものです。uji:tableタグは、インタフェースで得られる情報に従って表・行・セルといった単位でレンダラを呼び出し、その内容を画面に出力します。レンダラを省略した場合には、予め決まったパターンを出力します。
最初のレンダラは表全体(type="table")のフォーマットを指定します。ここでは、TABLEタグにborderとwidthのアトリビュートを追加しています。uji:childrenタグは下位のレンダラの処理を行う指定です。
次のレンダラはセル(type="column")で状態がヘッダ(cls="header")のもののフォーマットを指定しています。ここではTHタグを使い、背景色を設定しています。uji:valueはセルの値を表示する指定です。 最後のレンダラは、セル(type="column")で状態が編集可能(cls="editable")のもののフォーマットの指定です。INPUTタグで入力したデータはApcoordinatorが自動的にデータBeanに反映します。これを可能にするため、uji:nameでは更新時の名前を自動生成しています。
uji:peTextModeタグは、Apworksのページエディタに対する画面編集禁止の指定です。これは実行時は何も影響しません。
・SummaryModel.java

package model;

public class SummaryModel implements com.fujitsu.uji.model.table.TableModel {
    DataManager dm;

    public SummaryModel(DataManager dm) {
        this.dm = dm;
    }

    public int getColumnCount() {
        return 6;
    }

    public int getRowCount() {
        return dm.getDataCount() + 1;
    }

    public java.lang.Object getValueAt(int row, int col) {
        if(row == 0) {
            switch(col) {
                case 0: return "伝票番号";
                case 1: return "注文日";
                case 2: return "品番";
                case 3: return "数量";
                case 4: return "担当支店";
                case 5: return "納入予定日";
            }
        } else {
            MeisaiBean bean = dm.getData(row - 1);
            switch(col) {
                case 0:return bean.getDenpyoNo();
                case 1:return bean.getChumonDate();
                case 2:return bean.getShohinCode();
                case 3:return bean.getShohinCount();
                case 4:return bean.getTantoOffice();
                case 5:return bean.getNonyuDate();
            }
        }
        throw new ArrayIndexOutOfBoundsException();
    }

    public java.lang.String getColumnClass(int row, int col) {
        if(row == 0)
            return "header";
        else if(col == 5)
            return "editable";
        return null;
    }

    public java.lang.String getRowClass(int row) {
        return null;
    }

    public void setValueAt(java.lang.Object val, int row, int col) {
        if(row == 0 || col != 5 || !(val instanceof String))
            throw new IllegalStateException();
        MeisaiBean bean = dm.getData(row - 1);
        bean.setNonyuDate((String)val);
    }
}

表のインタフェースの実装クラスです。
getColumnCountメソッドとgetRowCountメソッドは、それぞれ表のカラム数と行数を返します。
getValueAtメソッドは、表中のセルのデータを返します。ここでは0行目をヘッダ用として使っています。また、データの行では概要表示の対象のみを選択して返しています。
getColumnClassメソッドは、セルのデータの状態を任意の文字列で返します。ここでは、0行目では"header"を、5カラム目では"editable"を返しています。その他の場合はデフォルトのレンダラを使うようにnullを返しています。
getRowClassメソッドは行のデータの状態を返しますが、ここではデフォルトを使用しています。
setValueAtメソッドは、データの更新のために呼ばれます。簡単なチェックの後、beanの更新を呼び出しています。
この例ではヘッダの文字列もクラス側から通知する仕組みとなっていますが、ヘッダの文字列はJSPに書いてクラス側ではデータのみを返すという方法もあります。後述の詳細表示は、ヘッダを固定文字列でJSPに書くタイプになっています。

■詳細表示(リストと複合Beanの画面部品を使用)

・detail.jsp

<%@ page contentType="text/html; charset=shift_jis" %>
<%@ taglib uri="uji-taglib" prefix="uji" %>
<uji:useBean id="body" cls="model.ModelBean" request="true" />
<P>納入予定日設定(詳細モード)</P>
<uji:peTextMode/>
<FORM method="post">
    <INPUT name="uji.verbs" type="hidden" value="showSummary"> 
    <INPUT name="uji.id" type="hidden" value="body">

<uji:list bean="body" property="detail">
  <uji:listRenderer type="list">
      <TABLE border="2" width="100%">
        <TR>
          <TH bgcolor="#EEFFEE" rowspan="2">伝票番号
          <TH bgcolor="#EEFFEE">注文日
          <TH bgcolor="#EEFFEE">品番
          <TH bgcolor="#EEFFEE">数量
          <TH bgcolor="#EEFFEE" colspan="2">顧客地区
          <TH bgcolor="#EEFFEE">納入予定日
        <TR>
          <TH bgcolor="#EEFFEE" colspan="3">商品名
          <TH bgcolor="#EEFFEE">担当支店
          <TH bgcolor="#EEFFEE">顧客名称
          <TH bgcolor="#EEFFEE">顧客電話番号
        <uji:children />
      </TABLE>
  </uji:listRenderer>
  <uji:listRenderer type="element">
    <uji:composite>
      <uji:compositeRenderer>
        <TR>
          <TD rowspan="2"><uji:getProperty property="denpyoNo" />
          <TD><uji:getProperty property="chumonDate" />
          <TD><uji:getProperty property="shohinCode" />
          <TD><uji:getProperty property="shohinCount" />
          <TD colspan="2"><uji:getProperty property="kokyakuWard" />
          <TD><input name="<uji:compositeName property='nonyuDate' />"
                     value="<uji:getProperty property='nonyuDate' />" >
        <TR>
          <TD colspan="3"><uji:getProperty property="shohinName" />
          <TD><uji:getProperty property="tantoOffice" />
          <TD><uji:getProperty property="kokyakuName" />
          <TD><uji:getProperty property="kokyakuPhone" />
      </uji:compositeRenderer>
    </uji:composite>
  </uji:listRenderer>
</uji:list>

    <INPUT name="showSummary" type="submit" value="概要表示"> 
</FORM>

この入出力ページでは、uji:listタグとuji:compositeタグを使用しています。
uji:listタグのアトリビュートでは、ListModelインタフェースを返すプロパティ名としてdetailを指定しています。
レンダラは2つあります。最初のレンダラはリスト全体のレンダラです。見出しの部分をTABLEタグを使って記述しています。 後のレンダラは、リストのエレメント(各行)のレンダラです。この例ではリストのエレメントは単純なデータではなく、データBeanになっています。そこで、さらにデータBeanの内容を参照するために、uji:compositeタグを利用しています。
uji:compositeタグではデータBeanを指定していません。これは上位の画面部品(ここではuji:list)からデータBeanを受け取っているためです。この例では、リストのエレメントとして返される値がMeisaiBeanクラスで、これがuji:compositeタグで使うデータBeanになります。
uji:compositeタグには、アトリビュートをもたないレンダラを1つ書きます。compositeRendererの中では値の参照にuji:getPropertyタグ、また更新時の名前の指定にuji:compositeNameタグを書きます。この例はデータを2段にフォーマットし、納入予定日を更新可能にしています。
・DetailModel.java

package model;

public class DetailModel implements com.fujitsu.uji.model.list.ListModel {
    DataManager dm;

    public DetailModel(DataManager dm) {
        this.dm = dm;
    }

    public int getSize() {
        return dm.getDataCount();
    }

    public java.lang.Object getElementAt(int pos) {
        return dm.getData(pos);
    }

    public java.lang.String getElementClass(int pos) {
        return null;
    }

    public void setElementAt(java.lang.Object obj, int pos) {
        throw new IllegalStateException();
    }
}

リストのインタフェースを実装するクラスです。
getSizeメソッドはリストのエレメントの数を返します。
getElementAtメソッドはリストのエレメントのデータを返します。ここでは、DataManagerクラスから受け取ったMeisaiBeanオブジェクトをそのまま返しています。
getElementClassメソッドはデータの状態を返しますが、ここでは全てデフォルトです。
setElementAtメソッドはここでは呼ばれません。リストのエレメントが文字列などの単純なデータでuji:nameタグで入力フィールドを指定するときはsetElementAtでデータを受け取りますが、この場合はuji:compositeタグを介して入力フィールドを設定しているため、MeisaiBeanのsetメソッドが直接呼ばれることになります。
目次 前ページ次ページ

All Rights Reserved, Copyright © 富士通株式会社 2000-2005