select-test

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<title>テスト</title>
<style>
body {
  font-size: 9pt;
  color: #000000;
  background-color:#ffffff;
}
</style>
<script>
function setSelect(obj, target, defaultIndex) {
	var element = document.getElementById(target); 
	for (var i=0;i<element.options.length;i++) { 
		if (obj.value == element.options[i].value) {
			element.options[i].selected = "true";
			return;
		}
	}
	obj.value = "";
	element.options[defaultIndex].selected = "true";
}

function selectChange(val, target) {
	document.getElementById(target).value = val;
}
</script>
</head>

<body>
	<input type="text" id="text" maxlength="1" onblur="setSelect(this, 'select', 0)"/>
	<select id="select" onChange="selectChange(this.value, 'text')">
		<option value=" " selected></option>
		<option value="1">1</option>
		<option value="2">2</option>
		<option value="3">3</option>
		<option value="4">4</option>
		<option value="5">5</option>
	</select>
</body>
</html>


rest-manager

rest.csv

2010/10/05,テストさん,15:15,15:30,テストだよ。,
2010/10/05,テストさん,15:30,16:00,テストだよ。,

RestViewer.html

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<title>休憩管理ビューワー</title>
<style>
body {
  font-size: 9pt;
  color: #000000;
  background-color:#ffffff;
}
select {
  font-size: 9pt;
  color: #000000;
}

.button1 {
	width: 80px;
	font-weight: bold;
}

.button2 {
	width: 120px;
	font-weight: bold;
}

.table {
  border: 1px solid black;
}

.table-header1 {
  font-size: 9pt;
  font-weight: normal;
  text-align: center;
  background-color: #9999ff;
}

.table-record1 {
  border: 1px solid black;
  font-size:9pt;
  background-color: #ffffff;
}

.table-record2 {
  border: 1px solid black;
  font-size: 9pt;
  background-color: #ccccff;
}

.table-data1 {
  border-bottom: 1px solid black;
  border-right: 1px solid black;
  font-size:9pt;
}

.title1 {
	font-weight: bold;
  font-size: 12pt;
  color: #ffffff;
  text-decoration: underline;
  background-color: #9999ff;
  padding: 2pt 2pt 2pt 2pt;
}

.title-background-color {
  background-color: #6666ff;
}

</style>
<script>
var baseDir = "";
var tempPath = location.pathname;
var path = tempPath.split("/");
for (i=0; i<path.length-1; i++) {
	if (path[i] != "") {
		baseDir += path[i] + "/";
	}
}
var src = src = baseDir + "rest.csv";
var fil1 = "";
var fil2 = "";
var fil3 = "";


//******************************************************************************
//
// ソート
//
//******************************************************************************
function sort(argCol) {
  var sortId = "";
  if (argCol.value.indexOf("▲") != -1) {
    argCol.value = argCol.value.replace("▲", "▼");
    sortId = "-" + argCol.id
  } else if (argCol.value.indexOf("▼") != -1) {
    argCol.value = argCol.value.replace("▼", "▲");
    sortId = argCol.id
  } else {
    argCol.value = "▲" + argCol.value;
    sortId = argCol.id
  }

  tdc.Sort = sortId;
  tdc.Reset();

	var rs = tdc.recordset;
	cnt.innerText = rs.RecordCount;

  var presortid = document.f.presortId.value;
  if (presortid != "" && argCol.id != presortid) {
    var presort = document.all.item(presortid);
    presort.value = presort.value.replace("▲", "");
    presort.value = presort.value.replace("▼", "");
  }
  document.f.presortId.value = argCol.id;
}

//******************************************************************************
//
// フィルタ
//
//******************************************************************************
function filter() {
	var fil = "";
	var con = "&";
	if (document.f.condition[1].checked) {
		con = "|";
	}

	if (fil1 != "") {
		fil += fil1;
  }

	if (fil2 != "") {
		if (fil != "") {
			fil += " " + con + " ";
		}
		fil += fil2;
  }

	if (fil3 != "") {
		if (fil != "") {
			fil += " " + con + " ";
		}
		fil += fil3;
	}

  tdc.Filter = fil;
  tdc.Reset();

	var rs = tdc.recordset;
	cnt.innerText = rs.RecordCount;
}

//******************************************************************************
//
// フィルタ
//
//******************************************************************************
function setFilter() {

	  var tgt1 = document.f.filterTarget1.value;
	  var val1 = document.f.filterValue1.value;
		if (tgt1 != "" && val1 != "") {
		  fil1 = "(" + tgt1 + " = *" + val1 + "*)";
		} else {
		  document.f.filterTarget1.value = "";
		  document.f.filterValue1.value = "";
		}
	  var tgt2 = document.f.filterTarget2.value;
	  var val2 = document.f.filterValue2.value;
		if (tgt2 != "" && val2 != "") {
		  fil2 = "(" + tgt2 + " = *" + val2 + "*)";
		} else {
		  document.f.filterTarget2.value = "";
		  document.f.filterValue2.value = "";
		}
	  var tgt3 = document.f.filterTarget3.value;
	  var val3 = document.f.filterValue3.value;
		if (tgt3 != "" && val3 != "") {
		  fil3 = "(" + tgt3 + " = *" + val3 + "*)";
		} else {
		  document.f.filterTarget3.value = "";
		  document.f.filterValue3.value = "";
		}

	filter();
}

//******************************************************************************
//
// フィルタクリア
//
//******************************************************************************
function filterClear(argIdx) {
	if (argIdx == 1) {
	  fil1 = "";
	  document.f.filterTarget1.value = "";
	  document.f.filterValue1.value = "";
  } else if (argIdx == 2) {
	  fil2 = "";
	  document.f.filterTarget2.value = "";
	  document.f.filterValue2.value = "";
  } else if (argIdx == 3) {
	  fil3 = "";
	  document.f.filterTarget3.value = "";
	  document.f.filterValue3.value = "";
	}
}

//******************************************************************************
//
// 初期表示
//
//******************************************************************************
function bodyOnload() {
  document.f.filterTarget1.value = "";
  document.f.filterValue1.value = "";
  document.f.filterTarget2.value = "";
  document.f.filterValue2.value = "";
  document.f.filterTarget3.value = "";
  document.f.filterValue3.value = "";
	tdc.DataURL = src;
  tdc.Filter = "";
  tdc.Sort = "-column1";
	tdc.Reset();

	var rs = tdc.recordset;
	cnt.innerText = rs.RecordCount;

	var date = new Date();
	year = date.getYear();
	month = date.getMonth() + 1;
	if (month < 10) {
		month = "0" + month;
	}
	day = date.getDate();
	if (day < 10) {
		day = "0" + day;
	}
	hours = date.getHours();
	minutes = date.getMinutes();

	document.getElementById("date").value = year + "/" + month + "/" + day;
	document.getElementById("restStart").value = hours + ":" + minutes;
	document.getElementById("restEnd").value = hours + ":" + minutes;

}

//******************************************************************************
//
// 再表示
//
//******************************************************************************
function refresh() {
	tdc.DataURL = src;
	tdc.Reset();

	var rs = tdc.recordset;
	cnt.innerText = rs.RecordCount;
}

//******************************************************************************
//
// 登録
//
//******************************************************************************
function append() {
	var appendData = document.f.elements["appendData"];
	var csv = "";
	for (i=0; i<appendData.length; i++) {
		if (appendData[i].value == "") {
			appendData[i].value = " ";
		}
		csv += appendData[i].value + ",";
	}

	var fso = new ActiveXObject("Scripting.FileSystemObject");
	var writer = fso.OpenTextFile(src, 8);
	writer.WriteLine(csv);
	writer.Close();
	refresh();
}

</script>
</head>

<body onload="bodyOnload()">
<table width="100%">
  <tr class="title-background-color">
    <td class="title1" id="titleName">休憩管理</td>
  </tr>
</table>


<object id="tdc" classid="clsid:333C7BC4-460F-11D0-BC04-0080C7055A83">
	<param name="DataURL" value="">
	<param name="CharSet" value="Shift_JIS">
</object>
<form name="f">
	<span>フィルタ設定</span>
	<select name="filterTarget1">
		<option value="NoFilter"></option>
		<option value="column1">日付</option>
		<option value="column2">名前</option>
		<option value="column3">休憩開始</option>
		<option value="column4">休憩終了</option>
		<option value="column5">コメント</option>
	</select>
	<input type="text" name="filterValue1" size="20">
	<input class="button1" type="button" name="setclear1" value="クリア" onclick="filterClear(1)">
	<br>
	<span>フィルタ設定</span>
	<select name="filterTarget2">
		<option value="NoFilter"></option>
		<option value="column1">日付</option>
		<option value="column2">名前</option>
		<option value="column3">休憩開始</option>
		<option value="column4">休憩終了</option>
		<option value="column5">コメント</option>
	</select>
	<input type="text" name="filterValue2" size="20">
	<input class="button1" type="button" name="setclear2" value="クリア" onclick="filterClear(2)">
	<br>
	<span>フィルタ設定</span>
	<select name="filterTarget3">
		<option value="NoFilter"></option>
		<option value="column1">日付</option>
		<option value="column2">名前</option>
		<option value="column3">休憩開始</option>
		<option value="column4">休憩終了</option>
		<option value="column5">コメント</option>
	</select>
	<input type="text" name="filterValue3" size="20">
	<input class="button1" type="button" name="setclear3" value="クリア" onclick="filterClear(3)">
	<br>
	<span>フィルタ条件</span>
	<input type="radio" name="condition" id="conditionAnd" value="&" checked>
	<label for="conditionAnd"><span>AND</span></label>
	<input type="radio" name="condition" id="conditionOr" value="|">
	<label for="conditionOr"><span>OR</span></label>
	<input class="button1" type="button" name="setfilter1" value="設 定" onclick="setFilter()">
	<br>
	<hr>
	<button class="button1" onclick="tb1.previousPage()">前ページ</button>
	<button class="button1" onclick="tb1.nextPage()">次ページ</button>
	<button class="button1" onclick="refresh()">再表示</button>
	<input type="hidden" name="presortId" value="column1">
	<span>全 </span>
	<span id="cnt"></span>
	<span> 件</span>
	<br>
	<br>
	<table class="table" datasrc="#tdc" id="tb1" datapagesize="10" cellspacing="0" cellpadding="3">
		<thead>
			<tr class="table-header1">
			<th class="table-data1"><input class="button2" type="button" onclick="sort(this)" id="column1" value="▼日付"></th>
			<th class="table-data1"><input class="button2" type="button" onclick="sort(this)" id="column2" value="名前"></th>
			<th class="table-data1"><input class="button2" type="button" onclick="sort(this)" id="column3" value="休憩開始"></th>
			<th class="table-data1"><input class="button2" type="button" onclick="sort(this)" id="column4" value="休憩終了"></th>
			<th class="table-data1"><input class="button2" type="button" onclick="sort(this)" id="column5" value="コメント"></th>
			</tr>
		</thead>
		<tr class="table-record1">
			<td class="table-data1" nowrap><span datafld="column1"></span></td>
			<td class="table-data1"><span datafld="column2"></span></td>
			<td class="table-data1" nowrap><span datafld="column3"></span></td>
			<td class="table-data1" nowrap><span datafld="column4"></span></td>
			<td class="table-data1"><span datafld="column5"></span></td>
		</tr>
	</table>
	<br>
	<hr>
	<span style="font-family:monospace;">日付   </span><input type="text" name="appendData" id="date" value="">
	<br>
	<span style="font-family:monospace;">名前   </span><input type="text" name="appendData" id="name" value="">
	<br>
	<span style="font-family:monospace;">休憩開始 </span><input type="text" name="appendData" id="restStart" value="">
	<br>
	<span style="font-family:monospace;">休憩終了 </span><input type="text" name="appendData" id="restEnd" value="">
	<br>
	<span style="font-family:monospace;">コメント </span><input type="text" name="appendData" id="comment" value="">
	<br>
	<button class="button1" onclick="append()">登録</button>
</form>
</body>
</html>

jqueryをはじめる

jQuery入門(その1) (1/7):CodeZine(コードジン)
を参考にjqueryを始めてみた。


会員登録しないと全部の記事が見れないみたいだから、続きはお家で。


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
<title>jquery sample</title>
<script src="scripts/jquery-1.3.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
<!--
$(function(){
  $("#gdEntries").css("border", "solid 1px navy");
  $(".gridalternate").css("background", "lightsteelblue");
  $("#gdEntries>tbody>tr>td[id^=Pk]").css("background", "#DDFFCC");
});

$(function(){
  $("input:text")
    .blur(function(){
      $(this).css("backgroundColor", "white");
    })
    .focus(function(){
      $(this).css("backgroundColor", "#FFCCDD");
    });

  $("input:button,input:submit") 
    .click(function(event){     
      alert("clicked");  
    });
});
//-->
</script>
</head>
<body>
  <table id="gdEntries">
    <tr>
     <td>a</td>
     <td>b</td>
    </tr>
    <tr>
     <td id="Pk">c</td>
     <td id="Pk">d</td>
    </tr>
  </table>
  <table class="gridalternate">
    <tr>
     <td>a</td><td>b</td>
    </tr>
    <tr>
     <td>c</td><td>d</td>
    </tr>
  </table>
  <input type="text"/>
  <input type="button" value="ボタン"/>
</body>
</html>

docletとpoiを使ってみる

以前のテストプチフレームワークづくりの続き。


テスト結果を比較する際に、期待する結果を記述するExcelファイルの作成を支援するツール。(あくまでベース)
こんな感じかな。


import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;

import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.RootDoc;

public class CreateExceptSheet {

  enum Type {
    JAVA_DOC, FIELD_NAME
  }

  /**
   * @param root
   * @return
   */
  public static boolean start(RootDoc root) {
    try {
      CreateExceptSheet ces = new CreateExceptSheet();
      List<Map<Type, String>> column = ces.getColumn(root);
      ces.createXlsFile(column);
      return true;
    } catch (Exception e) {
      return false;
    }
  }

  /**
   * @param root
   * @return
   */
  private List<Map<Type, String>> getColumn(RootDoc root) {
    List<Map<Type, String>> ret = new ArrayList<Map<Type, String>>();
    for (ClassDoc clazz : root.classes()) {
      for (MethodDoc method : clazz.methods()) {
        if (method.name().matches("^get.+$")) {
          Map<Type, String> entry = new HashMap<Type, String>();
          entry.put(
            Type.FIELD_NAME,
            method.name().replace("get","")
          );
          entry.put(
            Type.JAVA_DOC,
            method.tags("@return")[0].text()
          );
          ret.add(entry);
        }
      }
    }
    return ret;
  }

  /**
   * @param column
   * @throws IOException
   */
  private void createXlsFile(List<Map<Type, String>> column)
      throws IOException {
    OutputStream xlsFile = null;
    try {
      HSSFWorkbook workBook = new HSSFWorkbook();
      HSSFSheet sheet = workBook.createSheet("sample");
      HSSFCellStyle style = createCellStyle(workBook);
      int rowCount = 0;
      for (Type key : Type.values()) {
        HSSFRow row = sheet.createRow(rowCount++);
        int cellCount = 0;
        for (Map<Type, String> entry : column) {
          HSSFCell cell = row.createCell(cellCount++);
          cell.setCellStyle(style);
          cell.setCellValue(entry.get(key));
        }
      }
      // sheet.createFreezePane(0, 0, 0, 1);
      xlsFile = new FileOutputStream("except.xls");
      workBook.write(xlsFile);
    } finally {
      if (xlsFile != null) {
        xlsFile.close();
      }
    }
  }

  /**
   * @param workBook
   * @return
   */
  private HSSFCellStyle createCellStyle(HSSFWorkbook workBook) {
    HSSFFont font = workBook.createFont();
    font.setFontHeightInPoints((short) 11);
    font.setFontName("MS Pゴシック");
    HSSFCellStyle style = workBook.createCellStyle();
    style.setFont(font);
    style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
    style.setBottomBorderColor(HSSFColor.BLACK.index);
    style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
    style.setLeftBorderColor(HSSFColor.BLACK.index);
    style.setBorderRight(HSSFCellStyle.BORDER_THIN);
    style.setRightBorderColor(HSSFColor.BLACK.index);
    style.setBorderTop(HSSFCellStyle.BORDER_THIN);
    style.setTopBorderColor(HSSFColor.BLACK.index);
    style.setFillBackgroundColor(HSSFColor.BLUE.index);
    return style;
  }

}

やる気がでる言葉

今日たまたま、こんな言葉と見つけたよ。

10年後にはきっと、せめて10年でいいからもどってやり直したいと思っているのだろう。
今やり直せよ。未来を。
10年後か、20年後か、50年後から戻ってきたんだよ今。

2ちゃんねるの書き込みみたい)



すごい心に響く言葉だな。


やる気がでてきたよ。

ダイナミックプロキシを使ってみる

あるフレームワークを使って構築しているWebアプリケーションのテストクラスを作成したくて、試行錯誤している途中。

テストクラスを作成するうえでフレームワークのコアな部分の知識は必須となるから、すごく勉強になる。

目標はフレームワークに依存する部分以外は、『pure java』。


、、、でも




、、、作成途中どうしてもmockを利用しなきゃ対処できない状況に陥った。。
(自分のスキル不足かな)




でも、djUnitやeasyMockは使用したくない。
(変な意地かな)


そこで調べたら、ダイナミックプロキシが使えるかなって思って、以下のようなプチモックを提供するクラスを実装してみた。
(実際、easyMockもこれを使っているみたい)


実装内容

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

public class MockHandler implements InvocationHandler {
	private Object proxy;
	private Object targetObject = null;
	private Class<?> targetClass = null;
	private Map<Method, Object> returnValues = new HashMap<Method, Object>();

	/**
	 * コンストラクタ<br>
	 *
	 * @param target 起動対象クラス
	 */
	public MockHandler(Class<?> target) {
		if (target == null || !target.isInterface()) {
			throw new IllegalArgumentException("targetはinterfaceを指定してください。");
		}
		createProxy(target);
	}

	/**
	 * コンストラクタ
	 *
	 * @param target 起動対象オブジェクト
	 */
	public MockHandler(Object target) {
		if (target == null) {
			throw new IllegalArgumentException("targetを指定してください。");
		}
		targetObject = target;
		createProxy(target.getClass());
	}

	/**
	 * プロキシインスタンスの生成をします。
	 *
	 * @param target 対象クラス
	 */
	private void createProxy(Class<?> target) {
		targetClass = target;
		try {
//			Class<?> proxyClass = Proxy.getProxyClass(target.getClassLoader(),
//					new Class[] { target });
//			proxy = proxyClass.getConstructor(
//					new Class[] { InvocationHandler.class }).newInstance(
//					new Object[] { this });
			proxy = Proxy.newProxyInstance(target.getClassLoader(),
					new Class[] { target }, this);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * プロキシインスタンスを取得します。
	 *
	 * @return プロキシオブジェクト
	 **/
	public Object getProxyObject() {
		return proxy;
	}

	/**
	 * 指定したメソッドの戻り値を設定します。
	 *
	 * @param methodName 定義メソッド
	 * @param returnValue 戻り値
	 */
	public void setReturnValue(String methodName, Object returnValue) {
		Method[] methods = targetClass.getMethods();
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				returnValues.put(method, returnValue);
			}
		}
	}

	/**
	 * プロキシインスタンスでメソッド呼び出しを処理し、その結果を返します。<br>
	 * 但し、{@link mock.MockHandler#setReturnValue()}にて、
	 * 指定したメソッドに対して戻り値を設定している場合は、その結果を返却します。
	 *
	 * @see java.lang.reflect.InvocationHandler
	 * #invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
	 */
	public Object invoke(Object obj, Method method, Object[] args) throws Throwable {

		if (returnValues.containsKey(method)) {
			return returnValues.get(method);
		}

        if (targetObject != null) {
            return method.invoke(targetObject, args);
        }
        int mod = method.getModifiers();
        if (!Modifier.isAbstract(mod)) {
            return method.invoke(obj, args);
        }

        Class<?> retType = method.getReturnType();
        if (!retType.isPrimitive()) {
            return retType.newInstance();
        } else {
            if (retType.isAssignableFrom(Integer.TYPE)) {
                return new Integer(0);
            } else if (retType.isAssignableFrom(Long.TYPE)) {
                return new Long(0);
            } else if (retType.isAssignableFrom(Short.TYPE)) {
                return new Short((short)0);
            } else if (retType.isAssignableFrom(Double.TYPE)) {
                return new Double(0);
            } else if (retType.isAssignableFrom(Float.TYPE)) {
                return new Float(0);
            } else if (retType.isAssignableFrom(Boolean.TYPE)) {
                return new Boolean(false);
            } else if (retType.isAssignableFrom(Character.TYPE)) {
                return new Character(' ');
            } else if (retType.isAssignableFrom(Byte.TYPE)) {
                return new Byte((byte)0);
            } else if (retType.isAssignableFrom(Void.TYPE)) {
                return null;
            }
        }
        return null;
    }
}

使用例

    MockHandler mock = new MockHandler(List.class);
    mock.setReturnValue("size", 10);
    List list = (List) mock.getProxyObject();
    System.out.println(list.size());

実行結果

10



わぉ!
これは使えそう。これでテストクラスの作成が進みそう。

AptanaStudioの日本語化

Jaxerの勉強をするために、開発環境にAptanaStudioを使うことにした。
AptantaStudioの日本語化についてのメモを残しておこう。


まず、以下のサイトから、Pleiades (プレアデス)をダウンロード。
Eclipse 日本語化 | MergeDoc Project


最新版と安定板があるけど、今回は安定板をチョイス。


ダウンロードしたzipファイルを解凍し、features、pluginフォルダをそれぞれ
AptanaStudio配下のfeatures、pluginフォルダにコピー。


AptanaStudio.iniファイルの末尾に以下の内容を追加。

-javaagent:plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar

これで完了。