[Jiemamy-notify] commit [1907] DatabaseImporterの整備。テストも追加。 /

Back to archive index

svnno****@sourc***** svnno****@sourc*****
2008年 9月 10日 (水) 23:49:46 JST


Revision: 1907
          http://svn.sourceforge.jp/cgi-bin/viewcvs.cgi?root=jiemamy&view=rev&rev=1907
Author:   daisuke_m
Date:     2008-09-10 23:49:45 +0900 (Wed, 10 Sep 2008)

Log Message:
-----------
DatabaseImporterの整備。テストも追加。 /
型名→SpecialDataTypeへの変換が、caseSensitiveだったので、ignoreCaseに修正。 /
ObservableListに、AbstractListの実装を混入。(toStringが欲しかっただけだが…) /
CreateNewForeignKeyProcessorのコンストラクタで、接続対象エンティティも指定させるようにした。→ アタッチが行われてしまう為。

Modified Paths:
--------------
    artemis/trunk/org.jiemamy.composer/src/main/java/org/jiemamy/composer/importer/DatabaseImporter.java
    artemis/trunk/org.jiemamy.composer/src/test/resources/test.dicon
    artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/extension/dialect/Dialect.java
    artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/extension/dialect/mapping/SpecialDataTypeMapping.java
    artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/RootModel.java
    artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/connection/AbstractConnectionModel.java
    artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/node/TableModel.java
    artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/typedef/ColumnModel.java
    artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/typedef/constraint/ConstraintSetModel.java
    artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/ForEachUtil.java
    artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/JmStringUtil.java
    artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/collectionimpl/ObservableList.java
    artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/processor/connection/AttachConnectionProcessor.java
    artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/processor/root/creation/CreateNewForeignKeyProcessor.java
    artemis/trunk/org.jiemamy.dialect/src/main/java/org/jiemamy/dialect/AbstractDialect.java
    artemis/trunk/org.jiemamy.dialect/src/test/java/org/jiemamy/dialect/test/DbConnectionTest.java

Added Paths:
-----------
    artemis/trunk/org.jiemamy.composer/src/test/java/org/jiemamy/composer/importer/
    artemis/trunk/org.jiemamy.composer/src/test/java/org/jiemamy/composer/importer/DatabaseImporterTest.java
    artemis/trunk/org.jiemamy.composer/src/test/resources/DatabaseImporterTest.dicon
    artemis/trunk/org.jiemamy.composer/src/test/resources/postgresql-8.3-603.jdbc3.jar
    artemis/trunk/org.jiemamy.dialect/src/test/java/org/jiemamy/dialect/AbstractDialectTest.java
    artemis/trunk/org.jiemamy.dialect/src/test/resources/AbstractDialectTest.dicon


-------------- next part --------------
Modified: artemis/trunk/org.jiemamy.composer/src/main/java/org/jiemamy/composer/importer/DatabaseImporter.java
===================================================================
--- artemis/trunk/org.jiemamy.composer/src/main/java/org/jiemamy/composer/importer/DatabaseImporter.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.composer/src/main/java/org/jiemamy/composer/importer/DatabaseImporter.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -67,6 +67,9 @@
 	/** ContextKey: importするエンティティ名 (String[]) */
 	public static final String SELECTED_ENTITIES = "selectedEntities";
 	
+	/** ContextKey: importするエンティティの種類 (String[]) */
+	public static final String ENTITY_TYPES = "entityTypes";
+	
 	/** SQL方言 */
 	private Dialect dialect;
 	
@@ -119,12 +122,6 @@
 		return true;
 	}
 	
-	private void throwIfNotNull(Exception e) throws Exception {
-		if (e != null) {
-			throw e;
-		}
-	}
-	
 
 	/**
 	 * {@link RootModel}にEntityをインポートする、{@link ResultSet}に対するビジター。
@@ -164,19 +161,30 @@
 		public EntityImportVisitor(Connection connection, RootModel rootModel, ImportContext ctx) {
 			this.connection = connection;
 			this.rootModel = rootModel;
-			entityTypes = Arrays.asList((String[]) ctx.getValue("entityTypes")); // FIXME entityTypesを定数化
-			selectedEntities = Arrays.asList((String[]) ctx.getValue(SELECTED_ENTITIES));
+			String[] entityTypesValue = ctx.getValue(ENTITY_TYPES);
+			if (entityTypesValue == null) {
+				entityTypesValue = new String[] {
+					"TABLE",
+					"VIEW"
+				};
+			}
+			entityTypes = Arrays.asList(entityTypesValue);
+			String[] selectedEntitiesValue = ctx.getValue(SELECTED_ENTITIES);
+			selectedEntities = selectedEntitiesValue == null ? null : Arrays.asList(selectedEntitiesValue);
 		}
 		
 		/**
 		 * {@inheritDoc}
 		 */
 		public Void visit(ResultSet entity) throws SQLException {
-			if (entityTypes.contains(entity.getString("TABLE_TYPE"))
-					&& selectedEntities.contains(entity.getString("TABLE_NAME"))) {
+			if ((entityTypes.contains(entity.getString("TABLE_TYPE")))
+					&& (selectedEntities == null || selectedEntities.contains(entity.getString("TABLE_NAME")))) {
 				AbstractEntityModel entityModel = dialect.createEntity(rootModel, entity, connection);
-				entityModel.setDescription(entity.getString("REMARKS"));
-				rootModel.getNodes().add(entityModel);
+				if (entityModel != null) {
+					entityModel.setDescription(entity.getString("REMARKS"));
+					// UNDONE 制約などその他情報なども
+//					rootModel.getNodes().add(entityModel);
+				}
 			}
 			return null;
 		}
@@ -228,7 +236,7 @@
 				if (source != null && target != null) {
 					ForeignKeyModel fkModel = fkModels.get(fkName);
 					if (fkModel == null) {
-						fkModel = rootModel.process(new CreateNewForeignKeyProcessor(fkName));
+						fkModel = rootModel.process(new CreateNewForeignKeyProcessor(fkName, source, target));
 						fkModel.setName(fkName);
 					}
 					
@@ -238,8 +246,6 @@
 					
 					fkModel.setName(fkName);
 					fkModel.getMappings().add(mapping);
-					fkModel.setSource(source);
-					fkModel.setTarget(target);
 					
 					fkModels.put(fkName, fkModel);
 				}

Added: artemis/trunk/org.jiemamy.composer/src/test/java/org/jiemamy/composer/importer/DatabaseImporterTest.java
===================================================================
--- artemis/trunk/org.jiemamy.composer/src/test/java/org/jiemamy/composer/importer/DatabaseImporterTest.java	                        (rev 0)
+++ artemis/trunk/org.jiemamy.composer/src/test/java/org/jiemamy/composer/importer/DatabaseImporterTest.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2007-2008 MIYAMOTO Daisuke, jiemamy.org and the Others.
+ * Created on 2008/09/10
+ *
+ * This file is part of Jiemamy.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.jiemamy.composer.importer;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.junit.Assert.assertThat;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.seasar.framework.unit.Seasar2;
+
+import org.jiemamy.core.extension.dialect.Dialect;
+import org.jiemamy.core.extension.importer.ImportContext;
+import org.jiemamy.core.extension.importer.Importer;
+import org.jiemamy.core.model.RootModel;
+import org.jiemamy.core.model.node.TableModel;
+import org.jiemamy.core.utils.processor.root.GetTableProcessor;
+
+/**
+ * TODO for daisuke
+ * @author daisuke
+ */
+ @ RunWith(Seasar2.class)
+public class DatabaseImporterTest {
+	
+	/** {@link DatabaseImporter} */
+	public Importer importer;
+	
+	private Dialect dialect;
+	
+	private Class<?> serialTypeClass;
+	
+
+	/**
+	 * @throws java.lang.Exception
+	 */
+	@Before
+	@SuppressWarnings("unchecked")
+	public void setUp() throws Exception {
+		URLClassLoader classLoader = new URLClassLoader(new URL[] {
+			new File("../org.jiemamy.dialect/target/classes").toURL(),
+			new File("../org.jiemamy.dialect.postgresql/target/classes").toURL()
+		});
+		
+		// FIXME 前者はComponentNotFoundRuntimeExceptionが飛ぶ。
+//		Dialect dialect = (Dialect) container.getComponent(Class.forName(model.getDialectClassName(), true, classLoader));
+		dialect =
+				(Dialect) Class.forName("org.jiemamy.dialect.postgresql.PostgresqlDialect", true, classLoader)
+					.newInstance();
+		serialTypeClass = Class.forName("org.jiemamy.dialect.postgresql.datatype.SerialDataType", true, classLoader);
+	}
+	
+	/**
+	 * @throws java.lang.Exception
+	 */
+	@After
+	public void tearDown() throws Exception {
+		dialect = null;
+	}
+	
+	/**
+	 * DBからのインポートテスト。
+	 * @throws Exception 
+	 */
+	@Test
+	public void test01_DBからのインポートテスト() throws Exception {
+		RootModel rootModel = new RootModel();
+		ImportContext ctx = new ImportContext();
+		ctx.setValue(DatabaseImporter.DIALECT, dialect);
+		ctx.setValue(DatabaseImporter.DATABASE_NAME, "jpoll");
+		ctx.setValue(DatabaseImporter.DRIVER_JAR_PATH, new URL[] {
+			new File("./src/test/resources/postgresql-8.3-603.jdbc3.jar").toURL()
+		});
+		ctx.setValue(DatabaseImporter.DRIVER_CLASS_NAME, "org.postgresql.Driver");
+		ctx.setValue(DatabaseImporter.URI, "jdbc:postgresql://localhost/jpoll");
+		ctx.setValue(DatabaseImporter.SCHEMA, "");
+		ctx.setValue(DatabaseImporter.USERNAME, "postgres");
+		ctx.setValue(DatabaseImporter.PASSWORD, "postgres");
+		ctx.setValue(DatabaseImporter.SELECTED_ENTITIES, null);
+		ctx.setValue(DatabaseImporter.ENTITY_TYPES, null);
+		importer.import_(rootModel, ctx);
+		
+		assertThat(rootModel.getNodes().size(), is(4));
+		assertThat(rootModel.getConnections().size(), is(5));
+		
+		TableModel pollTable = rootModel.process(new GetTableProcessor("t_poll"));
+		assertThat(pollTable.getName(), is("t_poll"));
+		assertThat(pollTable.getColumns().size(), is(11));
+		assertThat(pollTable.getColumns().get(0).getName(), is("poll_id"));
+		assertThat(pollTable.getColumns().get(0).getDataType(), instanceOf(serialTypeClass));
+		System.out.println(pollTable.getColumns().get(0).getConstraints());
+		
+		// UNDONE DatabaseImporter.java:185 を実装したら
+//		assertThat(pollTable.getColumns().get(0).getConstraints().has(PrimaryKeyConstraintModel.class), is(true));
+	}
+	
+}


Property changes on: artemis/trunk/org.jiemamy.composer/src/test/java/org/jiemamy/composer/importer/DatabaseImporterTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: artemis/trunk/org.jiemamy.composer/src/test/resources/DatabaseImporterTest.dicon
===================================================================
--- artemis/trunk/org.jiemamy.composer/src/test/resources/DatabaseImporterTest.dicon	                        (rev 0)
+++ artemis/trunk/org.jiemamy.composer/src/test/resources/DatabaseImporterTest.dicon	2008-09-10 14:49:45 UTC (rev 1907)
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
+	"http://www.seasar.org/dtd/components24.dtd">
+<components>
+	<component class="org.jiemamy.composer.importer.DatabaseImporter"/>
+</components>

Copied: artemis/trunk/org.jiemamy.composer/src/test/resources/postgresql-8.3-603.jdbc3.jar (from rev 1901, artemis/trunk/org.jiemamy.dialect/src/test/resources/postgresql-8.3-603.jdbc3.jar)
===================================================================
(Binary files differ)


Property changes on: artemis/trunk/org.jiemamy.composer/src/test/resources/postgresql-8.3-603.jdbc3.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream
Name: svn:mergeinfo
   + 

Modified: artemis/trunk/org.jiemamy.composer/src/test/resources/test.dicon
===================================================================
--- artemis/trunk/org.jiemamy.composer/src/test/resources/test.dicon	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.composer/src/test/resources/test.dicon	2008-09-10 14:49:45 UTC (rev 1907)
@@ -4,4 +4,5 @@
 <components>
 	<include path="aop.dicon"/>
 	<include path="jiemamy-core.dicon"/>
+	<include path="jiemamy-dialect.dicon"/>
 </components>

Modified: artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/extension/dialect/Dialect.java
===================================================================
--- artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/extension/dialect/Dialect.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/extension/dialect/Dialect.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -38,6 +38,9 @@
 	
 	/**
 	 * エンティティ情報から{@link AbstractEntityModel}を生成する。
+	 * 
+	 * <p>渡したEntity情報がTABLEやVIEWではなかった場合(INDEX等)<code>null</code>を返す。</p>
+	 * 
 	 * @param rootModel 
 	 * @param entity エンティティ情報
 	 * @param connection DB接続

Modified: artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/extension/dialect/mapping/SpecialDataTypeMapping.java
===================================================================
--- artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/extension/dialect/mapping/SpecialDataTypeMapping.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/extension/dialect/mapping/SpecialDataTypeMapping.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -21,17 +21,17 @@
 import java.util.Collection;
 import java.util.List;
 
-import org.apache.commons.lang.ArrayUtils;
 import org.seasar.framework.util.tiger.CollectionsUtil;
 
 import org.jiemamy.core.exception.DataTypeNotFoundException;
 import org.jiemamy.core.exception.IllegalDataTypeImplementationException;
 import org.jiemamy.core.exception.IllegalDialectImplementation;
+import org.jiemamy.core.model.typedef.datatype.AbstractDataType;
 import org.jiemamy.core.model.typedef.datatype.DataType;
 import org.jiemamy.core.model.typedef.datatype.GeneralDataType;
-import org.jiemamy.core.model.typedef.datatype.AbstractDataType;
 import org.jiemamy.core.model.typedef.datatype.SpecialDataType;
 import org.jiemamy.core.model.typedef.datatype.adapter.DataTypeAdapter;
+import org.jiemamy.core.utils.JmStringUtil;
 
 /**
  * 特殊SQL方言における、データ型同士のマッピング情報を保持するクラス。
@@ -116,8 +116,8 @@
 	 */
 	public SpecialDataType resolveSpecialDataType(String typeName) throws DataTypeNotFoundException {
 		for (Class<? extends AbstractDataType> clazz : classes) {
-			if (clazz.getAnnotation(MappingInfo.class).typeName().equals(typeName)
-					|| ArrayUtils.contains(clazz.getAnnotation(MappingInfo.class).alias(), typeName)) {
+			if (clazz.getAnnotation(MappingInfo.class).typeName().equalsIgnoreCase(typeName)
+					|| JmStringUtil.containsIgnoreCase(clazz.getAnnotation(MappingInfo.class).alias(), typeName)) {
 				try {
 					return (SpecialDataType) clazz.newInstance();
 				} catch (InstantiationException e) {

Modified: artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/RootModel.java
===================================================================
--- artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/RootModel.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/RootModel.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -21,6 +21,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+
 import org.jiemamy.core.model.connection.AbstractConnectionModel;
 import org.jiemamy.core.model.dataset.InsertDataSetModel;
 import org.jiemamy.core.model.node.AbstractNodeModel;
@@ -240,6 +243,14 @@
 		this.schemaName = schemaName;
 	}
 	
+//	/**
+//	 * {@inheritDoc}
+//	 */
+//	@Override
+//	public String toString() {
+//		return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
+//	}
+	
 	/**
 	 * コネクションのリストを設定する。
 	 * @param connections コネクションのリスト

Modified: artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/connection/AbstractConnectionModel.java
===================================================================
--- artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/connection/AbstractConnectionModel.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/connection/AbstractConnectionModel.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -18,6 +18,9 @@
  */
 package org.jiemamy.core.model.connection;
 
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+
 import org.jiemamy.core.model.AbstractModel;
 import org.jiemamy.core.model.node.AbstractNodeModel;
 
@@ -79,4 +82,12 @@
 	public void setTarget(T target) {
 		this.target = target;
 	}
+	
+//	/**
+//	 * {@inheritDoc}
+//	 */
+//	@Override
+//	public String toString() {
+//		return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
+//	}
 }

Modified: artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/node/TableModel.java
===================================================================
--- artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/node/TableModel.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/node/TableModel.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -101,6 +101,14 @@
 		return indexes;
 	}
 	
+//	/**
+//	 * {@inheritDoc}
+//	 */
+//	@Override
+//	public String toString() {
+//		return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
+//	}
+	
 	/**
 	 * テーブルCHECK制約のリストを設定する。
 	 * @param checks テーブルCHECK制約のリスト

Modified: artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/typedef/ColumnModel.java
===================================================================
--- artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/typedef/ColumnModel.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/typedef/ColumnModel.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -18,6 +18,9 @@
  */
 package org.jiemamy.core.model.typedef;
 
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+
 import org.jiemamy.core.model.AbstractModel;
 import org.jiemamy.core.model.typedef.constraint.Constraint;
 import org.jiemamy.core.model.typedef.constraint.ConstraintSetModel;
@@ -268,6 +271,14 @@
 		this.simpleIndex = simpleIndex;
 	}
 	
+//	/**
+//	 * {@inheritDoc}
+//	 */
+//	@Override
+//	public String toString() {
+//		return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
+//	}
+	
 	/**
 	 * 制約を設定する。
 	 * @param constraints   制約

Modified: artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/typedef/constraint/ConstraintSetModel.java
===================================================================
--- artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/typedef/constraint/ConstraintSetModel.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/model/typedef/constraint/ConstraintSetModel.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -21,6 +21,7 @@
 import java.util.Collection;
 import java.util.Map;
 
+import org.apache.commons.lang.ClassUtils;
 import org.seasar.framework.util.tiger.CollectionsUtil;
 
 import org.jiemamy.core.model.AbstractModel;
@@ -97,4 +98,21 @@
 		this.constraintMap = constraintMap;
 	}
 	
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append(super.toString());
+		sb.append("[");
+		for (Constraint constraint : constraintMap.values()) {
+			sb.append(ClassUtils.getShortClassName(constraint.getClass()));
+			sb.append(":");
+			sb.append(constraint.getName());
+			sb.append(", ");
+		}
+		sb.append("]");
+		return sb.toString();
+	}
 }

Modified: artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/ForEachUtil.java
===================================================================
--- artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/ForEachUtil.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/ForEachUtil.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -33,6 +33,7 @@
 	 * {@link Collection}を処理するビジターアクセプタメソッド。
 	 * @param <T> Collectionが持つオブジェクトの型
 	 * @param <R> 戻り値の型
+	 * @param <E> visitメソッドが投げる可能性のある例外
 	 * @param target 処理対象コレクション
 	 * @param visitor ビジター
 	 * @return accept結果
@@ -53,6 +54,7 @@
 	 * @param <K> Mapのキーの型
 	 * @param <V> Mapの値の型
 	 * @param <R> 戻り値の型
+	 * @param <E> visitメソッドが投げる可能性のある例外
 	 * @param targetMap 処理対象コレクション
 	 * @param visitor ビジター
 	 * @return accept結果
@@ -97,6 +99,7 @@
 	 * @author daisuke
 	 * @param <T> {@link Collection}が保持する型
 	 * @param <R> acceptが返すべき戻り値の型
+	 * @param <E> visitメソッドが投げる可能性のある例外
 	 */
 	public interface CollectionVisitor<T, R, E extends Exception> {
 		
@@ -110,6 +113,7 @@
 		 * 処理内容を記述するメソッド。
 		 * @param element 処理対象要素
 		 * @return 引き続きacceptを継続する場合null、ループを終了する場合acceptが返すべき戻り値を返す。
+		 * @throws E 
 		 */
 		R visit(T element) throws E;
 	}
@@ -120,6 +124,7 @@
 	 * @param <K> 処理対象{@link Map}のキーの型
 	 * @param <V> 処理対象{@link Map}の値の型
 	 * @param <R> forEachが返すべき戻り値の型
+	 * @param <E> visitメソッドが投げる可能性のある例外
 	 */
 	public interface MapVisitor<K, V, R, E extends Exception> {
 		

Modified: artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/JmStringUtil.java
===================================================================
--- artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/JmStringUtil.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/JmStringUtil.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -20,12 +20,45 @@
 
 import java.util.Locale;
 
+import org.apache.commons.lang.ArrayUtils;
+
 /**
  * Stringユーティリティ。
  * @author wencheng
  */
 public final class JmStringUtil {
 	
+	public static boolean containsIgnoreCase(String[] array, String stringToFind) {
+		return indexOfIgnoreCase(array, stringToFind) != ArrayUtils.INDEX_NOT_FOUND;
+	}
+	
+	public static int indexOfIgnoreCase(String[] array, String stringToFind) {
+		return indexOfIgnoreCase(array, stringToFind, 0);
+	}
+	
+	public static int indexOfIgnoreCase(String[] array, String stringToFind, int startIndex) {
+		if (array == null) {
+			return ArrayUtils.INDEX_NOT_FOUND;
+		}
+		if (startIndex < 0) {
+			startIndex = 0;
+		}
+		if (stringToFind == null) {
+			for (int i = startIndex; i < array.length; i++) {
+				if (array[i] == null) {
+					return i;
+				}
+			}
+		} else {
+			for (int i = startIndex; i < array.length; i++) {
+				if (stringToFind.equalsIgnoreCase(array[i])) {
+					return i;
+				}
+			}
+		}
+		return ArrayUtils.INDEX_NOT_FOUND;
+	}
+	
 	/**
 	 * 文字列の1文字目を大文字にする。
 	 * 

Modified: artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/collectionimpl/ObservableList.java
===================================================================
--- artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/collectionimpl/ObservableList.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/collectionimpl/ObservableList.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -18,6 +18,7 @@
  */
 package org.jiemamy.core.utils.collectionimpl;
 
+import java.util.AbstractList;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
@@ -42,7 +43,7 @@
  * @author shin1ogawa
  */
 @SuppressWarnings("serial")
-public class ObservableList<T> implements List<T> {
+public class ObservableList<T> extends AbstractList<T> implements List<T> {
 	
 	/**
 	 * Listの実装をdecorateした{@link ObservableList}を返す。
@@ -85,6 +86,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public void add(int index, T element) {
 		fireChange(new ObservableCollectionChangeEvent<List<T>, T>(ObservableCollectionChangeEvent.Timing.BEFORE_ADD,
 				this, index, element));
@@ -101,6 +103,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public boolean add(T o) {
 		int index = list.size();
 		fireChange(new ObservableCollectionChangeEvent<List<T>, T>(ObservableCollectionChangeEvent.Timing.BEFORE_ADD,
@@ -119,6 +122,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public boolean addAll(Collection<? extends T> c) {
 		if (c != null && c.size() > 0) {
 			// add(T)に展開する。
@@ -135,6 +139,7 @@
 	 * Listの実装のaddAll()を直接呼び出す訳ではなく、{@link #add(Object)}に展開する。
 	 * {@inheritDoc}
 	 */
+	@Override
 	public boolean addAll(int index, Collection<? extends T> collection) {
 		if (collection != null && collection.size() > 0) {
 			for (T element : collection) {
@@ -161,6 +166,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public void clear() {
 		int index = 0;
 		// Eventを通知するために一旦別のListへ格納し直す。
@@ -188,6 +194,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public boolean contains(Object o) {
 		return list.contains(o);
 	}
@@ -195,6 +202,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public boolean containsAll(Collection<?> c) {
 		return list.containsAll(c);
 	}
@@ -202,6 +210,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public T get(int index) {
 		return list.get(index);
 	}
@@ -209,6 +218,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public int indexOf(Object o) {
 		return list.indexOf(o);
 	}
@@ -216,6 +226,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public boolean isEmpty() {
 		return list.isEmpty();
 	}
@@ -223,6 +234,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public Iterator<T> iterator() {
 		return list.iterator();
 	}
@@ -230,6 +242,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public int lastIndexOf(Object o) {
 		return list.lastIndexOf(o);
 	}
@@ -237,6 +250,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public ListIterator<T> listIterator() {
 		return list.listIterator();
 	}
@@ -244,6 +258,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public ListIterator<T> listIterator(int index) {
 		return list.listIterator(index);
 	}
@@ -251,6 +266,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public T remove(int index) {
 		T element = list.get(index);
 		fireChange(new ObservableCollectionChangeEvent<List<T>, T>(
@@ -269,6 +285,7 @@
 	 * {@inheritDoc}
 	 * THINK 指定された要素の存在チェックは行わずにbeforeRemoveを発生させる事になるが?
 	 */
+	@Override
 	@SuppressWarnings("unchecked")
 	public boolean remove(Object o) {
 		int index = list.indexOf(o);
@@ -287,6 +304,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public boolean removeAll(Collection<?> c) {
 		List<Object> removeList = new ArrayList<Object>();
 		Iterator<?> iterator = iterator();
@@ -318,6 +336,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public boolean retainAll(Collection<?> c) {
 		return list.retainAll(c);
 	}
@@ -333,6 +352,7 @@
 	 * @param element
 	 * @return T
 	 */
+	@Override
 	public T set(int index, T element) {
 		T oldElement = list.get(index);
 		fireChange(new ObservableCollectionChangeEvent<List<T>, T>(ObservableCollectionChangeEvent.Timing.BEFORE_SET,
@@ -346,6 +366,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public int size() {
 		return list.size();
 	}
@@ -353,6 +374,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public List<T> subList(int fromIndex, int toIndex) {
 		return list.subList(fromIndex, toIndex);
 	}
@@ -360,6 +382,7 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public Object[] toArray() {
 		return list.toArray();
 	}
@@ -367,10 +390,12 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override
 	public <U>U[] toArray(U[] a) {
 		return list.toArray(a);
 	}
 	
+	@Override
 	protected void removeRange(int fromIndex, int toIndex) {
 		for (int i = fromIndex; i <= toIndex; i++) {
 			// #remove(int)に展開する。

Modified: artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/processor/connection/AttachConnectionProcessor.java
===================================================================
--- artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/processor/connection/AttachConnectionProcessor.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/processor/connection/AttachConnectionProcessor.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -42,7 +42,7 @@
 	 */
 	public static AttachConnectionProcessor getInstance() {
 		if (singleton == null) {
-			singleton = new AttachConnectionProcessor();
+			singleton = (new AttachConnectionProcessor());
 		}
 		return singleton;
 	}
@@ -60,6 +60,9 @@
 	}
 	
 	private void attachSource(AbstractConnectionModel<? extends AbstractNodeModel> connectionModel) {
+		assert connectionModel != null;
+		assert connectionModel.getSource() != null;
+		assert connectionModel.getSource().getSourceConnections() != null;
 		if (connectionModel.getSource().getSourceConnections().contains(connectionModel) == false) {
 			connectionModel.getSource().getSourceConnections().add(connectionModel);
 		}

Modified: artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/processor/root/creation/CreateNewForeignKeyProcessor.java
===================================================================
--- artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/processor/root/creation/CreateNewForeignKeyProcessor.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.core/src/main/java/org/jiemamy/core/utils/processor/root/creation/CreateNewForeignKeyProcessor.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -34,34 +34,42 @@
 
 	/**
 	 * コンストラクタ。
+	 * @param name 外部キー名
+	 * @param source 制約テーブル
+	 * @param target 参照テーブル
 	 * @category instance creation
 	 */
-	public CreateNewForeignKeyProcessor() {
-		this(null);
+	public CreateNewForeignKeyProcessor(String name, TableModel source, TableModel target) {
+		this(name, source, target, false);
 	}
 	
 	/**
 	 * コンストラクタ。
-	 * @param name ダイアグラム名
+	 * @param name 外部キー名
+	 * @param source 制約テーブル
+	 * @param target 参照テーブル
+	 * @param create 参照先カラムと同名のカラムを生成して、そのカラムにマッピングする場合は<tt>true</tt>
+	 * 		既存のカラムにマッピングする場合は<tt>false</tt>を渡す。
 	 * @category instance creation
 	 */
-	public CreateNewForeignKeyProcessor(String name) {
+	public CreateNewForeignKeyProcessor(String name, TableModel source, TableModel target, boolean create) {
 		fkModel = (ForeignKeyModel) getContainer().getComponent(ForeignKeyModel.class);
 		fkModel.setName(name);
+		fkModel.setSource(source);
+		fkModel.setTarget(target);
+		fkModel.createMappings(create);
 	}
 	
 	/**
 	 * コンストラクタ。
-	 * @param source
-	 * @param target
-	 * @param create
+	 * @param source 制約テーブル
+	 * @param target 参照テーブル
+	 * @param create 参照先カラムと同名のカラムを生成して、そのカラムにマッピングする場合は<tt>true</tt>
+	 * 		既存のカラムにマッピングする場合は<tt>false</tt>を渡す。
 	 * @category instance creation
 	 */
 	public CreateNewForeignKeyProcessor(TableModel source, TableModel target, boolean create) {
-		fkModel = new ForeignKeyModel();
-		fkModel.setSource(source);
-		fkModel.setTarget(target);
-		fkModel.createMappings(create);
+		this(null, source, target, create);
 	}
 	
 	/**

Modified: artemis/trunk/org.jiemamy.dialect/src/main/java/org/jiemamy/dialect/AbstractDialect.java
===================================================================
--- artemis/trunk/org.jiemamy.dialect/src/main/java/org/jiemamy/dialect/AbstractDialect.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.dialect/src/main/java/org/jiemamy/dialect/AbstractDialect.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -25,6 +25,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.seasar.framework.util.tiger.CollectionsUtil;
+
 import org.jiemamy.core.exception.DataTypeNotFoundException;
 import org.jiemamy.core.exception.IllegalDataTypeMappingException;
 import org.jiemamy.core.extension.dialect.Dialect;
@@ -72,7 +74,7 @@
 	 * @param validator 
 	 * @category instance creation
 	 */
-	public AbstractDialect(IdentifierValidator validator) {
+	protected AbstractDialect(IdentifierValidator validator) {
 		this(validator, new DefaultQuoter());
 	}
 	
@@ -88,6 +90,14 @@
 	}
 	
 	/**
+	 * コンストラクタ。
+	 * <p>for test</p>
+	 * @category instance creation
+	 */
+	AbstractDialect() {
+	}
+	
+	/**
 	 * {@inheritDoc}
 	 */
 	public AbstractEntityModel createEntity(RootModel rootModel, ResultSet entity, Connection connection)
@@ -168,6 +178,9 @@
 			columnsResult = meta.getColumns("", null/* FIXME schema */, tableName, "%");
 			ForEachUtil.accept(columnsResult, new AbstractResultSetVisitor<List<ColumnModel>>() {
 				
+				/**
+				 * {@inheritDoc}
+				 */
 				public List<ColumnModel> visit(ResultSet element) throws SQLException {
 					AbstractDataType dataType;
 					try {
@@ -200,6 +213,14 @@
 					return null;
 				}
 				
+				/**
+				 * {@inheritDoc}
+				 */
+				@Override
+				protected void init() {
+					finalResult = CollectionsUtil.newArrayList();
+				}
+				
 			});
 			
 			keysResult = meta.getPrimaryKeys("", null/* FIXME schema */, tableName);
@@ -225,9 +246,9 @@
 			JmIOUtil.closeQuietly(keysResult);
 		}
 		
-		for (ColumnModel column : columns) {
-			tableModel.getColumns().add(column);
-		}
+//		for (ColumnModel column : columns) {
+//			tableModel.getColumns().add(column);
+//		}
 		
 		return tableModel;
 	}

Added: artemis/trunk/org.jiemamy.dialect/src/test/java/org/jiemamy/dialect/AbstractDialectTest.java
===================================================================
--- artemis/trunk/org.jiemamy.dialect/src/test/java/org/jiemamy/dialect/AbstractDialectTest.java	                        (rev 0)
+++ artemis/trunk/org.jiemamy.dialect/src/test/java/org/jiemamy/dialect/AbstractDialectTest.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2007-2008 MIYAMOTO Daisuke, jiemamy.org and the Others.
+ * Created on 2008/09/10
+ *
+ * This file is part of Jiemamy.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.jiemamy.dialect;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.Driver;
+import java.sql.DriverPropertyInfo;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import javax.sql.DataSource;
+import javax.sql.XADataSource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.seasar.extension.jdbc.util.ConnectionUtil;
+import org.seasar.framework.unit.Seasar2;
+import org.seasar.framework.util.ClassUtil;
+
+import org.jiemamy.core.model.RootModel;
+import org.jiemamy.core.model.node.AbstractEntityModel;
+import org.jiemamy.core.utils.JmIOUtil;
+import org.jiemamy.dialect.helper.JiemamyXADataSource;
+import org.jiemamy.dialect.test.DbConnectionTest;
+
+/**
+ * TODO for daisuke
+ * @author daisuke
+ */
+ @ RunWith(Seasar2.class)
+public class AbstractDialectTest {
+	
+	/** {@link XADataSource} */
+	public XADataSource xaDataSource;
+	
+	/** {@link DataSource} */
+	public DataSource dataSource;
+	
+	/** JDBCドライバ */
+	private Driver driver;
+	
+	private AbstractDialect dialect;
+	
+
+	/**
+	 * TODO for daisuke
+	 * @throws java.lang.Exception
+	 */
+	@Before
+	public void setUp() throws Exception {
+		dialect = new AbstractDialect() {
+		};
+		
+		ClassLoader classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+			
+			public ClassLoader run() {
+				return URLClassLoader.newInstance(new URL[] {
+					DbConnectionTest.class.getResource("/postgresql-8.3-603.jdbc3.jar")
+				});
+			}
+		});
+		Class<Driver> driverClass = (Class<Driver>) classLoader.loadClass("org.postgresql.Driver");
+		driver = new DriverWrapper((Driver) ClassUtil.newInstance(driverClass));
+	}
+	
+	/**
+	 * TODO for daisuke
+	 * @throws java.lang.Exception
+	 */
+	@After
+	public void tearDown() throws Exception {
+		dialect = null;
+		driver = null;
+	}
+	
+	/**
+	 * 接続テスト。
+	 * @throws Exception 
+	 */
+	@Test
+	public void test_接続テスト() throws Exception {
+		assertNotNull(dataSource);
+		assertNotNull(xaDataSource);
+		assertNotNull(driver);
+		
+		JiemamyXADataSource impl = (JiemamyXADataSource) xaDataSource;
+		impl.setDriver(driver);
+		impl.setURL("jdbc:postgresql://localhost/jpoll");
+		impl.setUser("postgres");
+		impl.setPassword("postgres");
+		
+		Connection connection = dataSource.getConnection();
+		assertNotNull(connection);
+		
+		RootModel rootModel = new RootModel();
+		DatabaseMetaData meta = connection.getMetaData();
+		ResultSet entities = meta.getTables(null, "", "%", null);
+		while (entities.next()) {
+			AbstractEntityModel entityModel = dialect.createEntity(rootModel, entities, connection);
+			System.out.println(entityModel);
+		}
+		
+		DatabaseMetaData metaData = ConnectionUtil.getMetaData(connection);
+		assertNotNull(metaData);
+		JmIOUtil.closeQuietly(connection);
+	}
+	
+
+	/**
+	 * JDBC Driverのラッパークラス。
+	 * ref. http://forum.java.sun.com/thread.jspa?threadID=703241&messageID=4077758
+	 * @author daisuke
+	 */
+	static class DriverWrapper implements Driver {
+		
+		private Driver driver;
+		
+
+		/**
+		 * コンストラクタ。
+		 * @param d 
+		 * @category instance creation
+		 * @see java.sql.Driver
+		 */
+		public DriverWrapper(Driver d) {
+			driver = d;
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 */
+		public boolean acceptsURL(String u) throws SQLException {
+			return driver.acceptsURL(u);
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 */
+		public Connection connect(String u, Properties p) throws SQLException {
+			return driver.connect(u, p);
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 */
+		public int getMajorVersion() {
+			return driver.getMajorVersion();
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 */
+		public int getMinorVersion() {
+			return driver.getMinorVersion();
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 */
+		public DriverPropertyInfo[] getPropertyInfo(String u, Properties p) throws SQLException {
+			return driver.getPropertyInfo(u, p);
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 */
+		public boolean jdbcCompliant() {
+			return driver.jdbcCompliant();
+		}
+	}
+}


Property changes on: artemis/trunk/org.jiemamy.dialect/src/test/java/org/jiemamy/dialect/AbstractDialectTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: artemis/trunk/org.jiemamy.dialect/src/test/java/org/jiemamy/dialect/test/DbConnectionTest.java
===================================================================
--- artemis/trunk/org.jiemamy.dialect/src/test/java/org/jiemamy/dialect/test/DbConnectionTest.java	2008-09-10 11:32:30 UTC (rev 1906)
+++ artemis/trunk/org.jiemamy.dialect/src/test/java/org/jiemamy/dialect/test/DbConnectionTest.java	2008-09-10 14:49:45 UTC (rev 1907)
@@ -77,7 +77,6 @@
 		});
 		Class<Driver> driverClass = (Class<Driver>) classLoader.loadClass("org.postgresql.Driver");
 		driver = new DriverWrapper((Driver) ClassUtil.newInstance(driverClass));
-		
 	}
 	
 	/**

Added: artemis/trunk/org.jiemamy.dialect/src/test/resources/AbstractDialectTest.dicon
===================================================================
--- artemis/trunk/org.jiemamy.dialect/src/test/resources/AbstractDialectTest.dicon	                        (rev 0)
+++ artemis/trunk/org.jiemamy.dialect/src/test/resources/AbstractDialectTest.dicon	2008-09-10 14:49:45 UTC (rev 1907)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
+	"http://www.seasar.org/dtd/components24.dtd">
+<components>
+</components>


Jiemamy-notify メーリングリストの案内
Back to archive index