/*
 * Copyright 2006-2011 the Seasar Foundation and the Others.
 *
 * 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.seasar.codegen.impl;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import java.io.File;
import java.net.URL;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jiemamy.JiemamyContext;
import org.jiemamy.model.column.JmColumn;
import org.jiemamy.model.table.JmTable;
import org.jiemamy.serializer.JiemamySerializer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.seasar.codegen.element.DataType;
import org.seasar.codegen.element.Field;
import org.seasar.codegen.element.LinkTable;
import org.seasar.codegen.element.PrimaryKey;
import org.seasar.codegen.element.Table;
import org.seasar.codegen.element.lang.JavaDataType;
import org.seasar.framework.unit.Seasar2;
import org.seasar.framework.util.ResourceUtil;

@RunWith(Seasar2.class)
public class JiemamyImportCodeDataTest {

    private JiemamyImportCodeData importCodeData;

    private JiemamyContext jiemamyContext;

    public void postBindFields() throws Exception {
        JiemamySerializer serializer = JiemamyContext.findSerializer();
        jiemamyContext = serializer.deserialize(ResourceUtil
                .getResourceAsStream("codegen.jiemamy"));
    }

    @Test
    public void testGetTable() {
        Set<JmTable> entityModels = jiemamyContext.getTables();
        for (JmTable entityModel : entityModels) {
            if (entityModel.getName().equals("EMP_TABLE")) {
                Table table = importCodeData.getTable(entityModel);
                assertThat(table.getTableName(), is("EMP_TABLE"));
                assertThat(table.getPrimaryKey().get(0).getField()
                        .getFieldName(), is("EMP_NO"));
                return;
            }
        }
        fail();
    }

    @Test
    public void testReadCodeData() throws Exception {
        URL url = ResourceUtil.getResource("codegen.jiemamy");
        File file = new File(url.toURI());
        Map<String, Table> tableMap = importCodeData.readCodeData(file);
        assertThat(tableMap.get("EMP_TABLE"), is(notNullValue()));
        assertThat(tableMap.get("DEPT_TABLE"), is(notNullValue()));
        // 外部キー
        Table table = tableMap.get("DEPT_TABLE");
        assertThat(table.getChildTable().get(0).getTableName(), is("EMP_TABLE"));
    }

    @Test
    public void testGetField() {
        Set<JmTable> entityModels = jiemamyContext.getTables();
        for (JmTable entityModel : entityModels) {
            if (entityModel.getName().equals("EMP_TABLE")) {
                {
                    JmColumn columnModel = entityModel.getColumn("EMP_NO");
                    Field field = importCodeData.getField(columnModel,
                            entityModel);
                    assertThat(field.getFieldName(), is("EMP_NO"));
                    assertThat(field.getFieldAttributeName(), is("社員番号"));
                    assertThat(field.getDefaultVal(), is(nullValue()));
                    assertThat(field.getFieldNameForDto(), is("EMP_NO"));
                    assertThat(field.getSequence(), is(nullValue()));
                    DataType dataType = field.getDataType();
                    assertThat(dataType.getColmnSize(), is(4));
                    assertThat(dataType.getDefaultVal(), is(""));
                    assertThat(dataType.isNotNull(), is(true));
                    assertThat(dataType.getPointNumber(), is(0));
                    assertThat(dataType.getDefaultVal(), is(""));
                    JavaDataType javaDataType = (JavaDataType) dataType
                            .getLangDataType();
                    assertThat(javaDataType.getClassName(), is("Integer"));
                    assertThat(javaDataType.getDefVal(), is(""));
                }
                {
                    JmColumn columnModel = entityModel.getColumn("SAL");
                    Field field = importCodeData.getField(columnModel,
                            entityModel);
                    assertThat(field.getDataType().getColmnSize(), is(7));
                    assertThat(field.getDataType().getPointNumber(), is(2));
                }
                return;
            }

        }
        fail();
    }

    @Test
    public void testGetPrimaryKey_主キーが自動採番でないの場合() {
        Collection<JmTable> entityModels = jiemamyContext.getTables();
        for (JmTable entityModel : entityModels) {
            if (entityModel.getName().equals("EMP_TABLE")) {
                {
                    {
                        JmColumn columnModel = entityModel.getColumn("EMP_NO");
                        Field field = importCodeData.getField(columnModel,
                                entityModel);
                        PrimaryKey key = importCodeData.getPrimaryKey(
                                entityModel, field);
                        assertThat(key, is(notNullValue()));
                        assertThat(key.getField().isUseIdentity(), is(false));
                        assertThat(key.getField().isUseSequence(), is(true));
                        assertThat(key.getField().getSequence(), is("AAA"));

                    }
                }
                return;
            }

        }
        fail();
    }

    public void testGetPrimaryKey_主キーでない場合() {
        Collection<JmTable> entityModels = jiemamyContext.getTables();
        for (JmTable entityModel : entityModels) {
            if (entityModel.getName().equals("EMP_TABLE")) {
                {
                    {
                        JmColumn columnModel = entityModel.getColumn("ENAME");
                        Field field = importCodeData.getField(columnModel,
                                entityModel);
                        PrimaryKey key = importCodeData.getPrimaryKey(
                                entityModel, field);
                        assertThat(key, is(nullValue()));

                    }

                }
                return;
            }

        }
        fail();
    }

    @Test
    public void testGetPrimaryKey_主キーが自動採番の場合() {
        Collection<JmTable> entityModels = jiemamyContext.getTables();
        for (JmTable entityModel : entityModels) {
            if (entityModel.getName().equals("DEPT_TABLE")) {
                {
                    {
                        JmColumn columnModel = entityModel.getColumn("DEPT_ID");
                        Field field = importCodeData.getField(columnModel,
                                entityModel);
                        PrimaryKey key = importCodeData.getPrimaryKey(
                                entityModel, field);
                        assertThat(key, is(notNullValue()));
                        assertThat(key.getField().isUseIdentity(), is(true));
                        assertThat(key.getField().isUseSequence(), is(false));
                    }
                }
                return;
            }

        }
        fail();
    }

    @Test
    public void testGetParentLink() {
        Set<JmTable> entityModels = jiemamyContext.getTables();
        for (JmTable entityModel : entityModels) {
            if (entityModel.getName().equals("EMP_TABLE")) {
                Table table = importCodeData.getTable(entityModel);
                List<LinkTable> parentLink = importCodeData.getParentLink(
                        entityModels, entityModel, table);
                assertThat(parentLink.size(), is(1));
                LinkTable linkTable = parentLink.get(0);
                assertThat(linkTable.getTableName(), is("DEPT_TABLE"));
                assertThat(linkTable.getChildFieldName(), is("DEPT_NO"));
                assertThat(linkTable.getParentFieldName(), is("DEPT_ID"));

                return;
            }

        }
        fail();
    }

}
