Package org.apache.cayenne.access

Source Code of org.apache.cayenne.access.DbLoaderTest

/*****************************************************************
*   Licensed to the Apache Software Foundation (ASF) under one
*  or more contributor license agreements.  See the NOTICE file
*  distributed with this work for additional information
*  regarding copyright ownership.  The ASF licenses this file
*  to you 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.apache.cayenne.access;

import java.sql.Types;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.unit.CayenneCase;

public class DbLoaderTest extends CayenneCase {

    protected DbLoader loader;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        loader = new DbLoader(getConnection(), getNode().getAdapter(), null);
    }

    public void testGetTableTypes() throws Exception {
        try {
            List tableTypes = loader.getTableTypes();

            assertNotNull(tableTypes);

            String tableLabel = getNode().getAdapter().tableTypeForTable();
            if (tableLabel != null) {
                assertTrue(
                        "Missing type for table '" + tableLabel + "' - " + tableTypes,
                        tableTypes.contains(tableLabel));
            }

            String viewLabel = getNode().getAdapter().tableTypeForView();
            if (viewLabel != null) {
                assertTrue(
                        "Missing type for view '" + viewLabel + "' - " + tableTypes,
                        tableTypes.contains(viewLabel));
            }
        }
        finally {
            loader.getConnection().close();
        }
    }

    public void testGetTables() throws Exception {
        try {

            String tableLabel = getNode().getAdapter().tableTypeForTable();

            List<DbEntity> tables = loader.getTables(null, null, "%", new String[] {
                tableLabel
            });

            assertNotNull(tables);

            boolean foundArtist = false;

            for (DbEntity table : tables) {
                if ("ARTIST".equalsIgnoreCase(table.getName())) {
                    foundArtist = true;
                    break;
                }
            }

            assertTrue("'ARTIST' is missing from the table list: " + tables, foundArtist);
        }
        finally {
            loader.getConnection().close();
        }
    }

    public void testLoadWithMeaningfulPK() throws Exception {
        try {

            DataMap map = new DataMap();
            String tableLabel = getNode().getAdapter().tableTypeForTable();

            loader.setCreatingMeaningfulPK(true);
           
            List<DbEntity> testLoader = loader.getTables(
                    null,
                    null,
                    "artist",
                    new String[] {
                        tableLabel
                    });
            if(testLoader.size()==0){
                testLoader = loader.getTables(
                        null,
                        null,
                        "ARTIST",
                        new String[] {
                            tableLabel
                        });
            }
           
            loader.loadDbEntities(map, testLoader);

            loader.loadObjEntities(map);
            ObjEntity artist = map.getObjEntity("Artist");
            assertNotNull(artist);
            ObjAttribute id = (ObjAttribute) artist.getAttribute("artistId");
            assertNotNull(id);
        }
        finally {
            loader.getConnection().close();
        }
    }

    /**
     * DataMap loading is in one big test method, since breaking it in individual tests
     * would require multiple reads of metatdata which is extremely slow on some RDBMS
     * (Sybase).
     */
    public void testLoad() throws Exception {
        try {
            boolean supportsUnique = getNode().getAdapter().supportsUniqueConstraints();
            boolean supportsLobs = getAccessStackAdapter().supportsLobs();
            boolean supportsFK = getAccessStackAdapter().supportsFKConstraints();

            DataMap map = new DataMap();
            String tableLabel = getNode().getAdapter().tableTypeForTable();

            // *** TESTING THIS ***
            loader.loadDbEntities(map, loader.getTables(null, null, "%", new String[] {
                tableLabel
            }));

            assertDbEntities(map);

            if (supportsLobs) {
                assertLobDbEntities(map);
            }

            // *** TESTING THIS ***
            loader.loadDbRelationships(map);

            if (supportsFK) {
                Collection rels = getDbEntity(map, "ARTIST").getRelationships();
                assertNotNull(rels);
                assertTrue(rels.size() > 0);

                // test one-to-one
                rels = getDbEntity(map, "PAINTING").getRelationships();
                assertNotNull(rels);

                // find relationship to PAINTING_INFO
                DbRelationship oneToOne = null;
                Iterator it = rels.iterator();
                while (it.hasNext()) {
                    DbRelationship rel = (DbRelationship) it.next();
                    if ("PAINTING_INFO".equalsIgnoreCase(rel.getTargetEntityName())) {
                        oneToOne = rel;
                        break;
                    }
                }

                assertNotNull("No relationship to PAINTING_INFO", oneToOne);
                assertFalse("Relationship to PAINTING_INFO must be to-one", oneToOne
                        .isToMany());
                assertTrue("Relationship to PAINTING_INFO must be to-one", oneToOne
                        .isToDependentPK());

                // test UNIQUE only if FK is supported...
                if (supportsUnique) {
                    assertUniqueConstraintsInRelationships(map);
                }
            }

            // *** TESTING THIS ***
            loader.setCreatingMeaningfulPK(false);
            loader.loadObjEntities(map);

            ObjEntity ae = map.getObjEntity("Artist");
            assertNotNull(ae);
            assertEquals("Artist", ae.getName());
            // assert primary key is not an attribute
            assertNull(ae.getAttribute("artistId"));
            if (supportsLobs) {
                assertLobObjEntities(map);
            }

            if (supportsFK) {
                Collection rels1 = ae.getRelationships();
                assertNotNull(rels1);
                assertTrue(rels1.size() > 0);
            }

            // now when the map is loaded, test
            // various things
            // selectively check how different types were processed
            if (getAccessStackAdapter().supportsColumnTypeReengineering()) {
                checkTypes(map);
            }
        }
        finally {
            loader.getConnection().close();
        }
    }

    private void assertUniqueConstraintsInRelationships(DataMap map) {
        // unfortunately JDBC metadata doesn't provide info for UNIQUE constraints....
        // cant reengineer them...

        // find rel to TO_ONEFK1
        /*
         * Iterator it = getDbEntity(map, "TO_ONEFK2").getRelationships().iterator();
         * DbRelationship rel = (DbRelationship) it.next(); assertEquals("TO_ONEFK1",
         * rel.getTargetEntityName()); assertFalse("UNIQUE constraint was ignored...",
         * rel.isToMany());
         */
    }

    private void assertDbEntities(DataMap map) {
        DbEntity dae = getDbEntity(map, "ARTIST");
        assertNotNull(
                "Null 'ARTIST' entity, other DbEntities: " + map.getDbEntityMap(),
                dae);
        assertEquals("ARTIST", dae.getName().toUpperCase());
        DbAttribute a = getDbAttribute(dae, "ARTIST_ID");
        assertNotNull(a);
        assertTrue(a.isPrimaryKey());
    }

    private void assertLobDbEntities(DataMap map) {
        DbEntity blobEnt = getDbEntity(map, "BLOB_TEST");
        assertNotNull(blobEnt);
        DbAttribute blobAttr = getDbAttribute(blobEnt, "BLOB_COL");
        assertNotNull(blobAttr);
        assertTrue(msgForTypeMismatch(Types.BLOB, blobAttr), Types.BLOB == blobAttr
                .getType()
                || Types.LONGVARBINARY == blobAttr.getType());
        DbEntity clobEnt = getDbEntity(map, "CLOB_TEST");
        assertNotNull(clobEnt);
        DbAttribute clobAttr = getDbAttribute(clobEnt, "CLOB_COL");
        assertNotNull(clobAttr);
        assertTrue(msgForTypeMismatch(Types.CLOB, clobAttr), Types.CLOB == clobAttr
                .getType()
                || Types.LONGVARCHAR == clobAttr.getType());
    }

    private void assertLobObjEntities(DataMap map) {
        ObjEntity blobEnt = map.getObjEntity("BlobTest");
        assertNotNull(blobEnt);
        // BLOBs should be mapped as byte[]
        ObjAttribute blobAttr = (ObjAttribute) blobEnt.getAttribute("blobCol");
        assertNotNull("BlobTest.blobCol failed to load", blobAttr);
        assertEquals("byte[]", blobAttr.getType());
        ObjEntity clobEnt = map.getObjEntity("ClobTest");
        assertNotNull(clobEnt);
        // CLOBs should be mapped as Strings by default
        ObjAttribute clobAttr = (ObjAttribute) clobEnt.getAttribute("clobCol");
        assertNotNull(clobAttr);
        assertEquals(String.class.getName(), clobAttr.getType());
    }

    private DbEntity getDbEntity(DataMap map, String name) {
        DbEntity de = map.getDbEntity(name);
        // sometimes table names get converted to lowercase
        if (de == null) {
            de = map.getDbEntity(name.toLowerCase());
        }

        return de;
    }

    private DbAttribute getDbAttribute(DbEntity ent, String name) {
        DbAttribute da = (DbAttribute) ent.getAttribute(name);
        // sometimes table names get converted to lowercase
        if (da == null) {
            da = (DbAttribute) ent.getAttribute(name.toLowerCase());
        }

        return da;
    }

    private DataMap originalMap() {
        return getNode().getDataMaps().iterator().next();
    }

    /**
     * Selectively check how different types were processed.
     */
    public void checkTypes(DataMap map) {
        DbEntity dbe = getDbEntity(map, "PAINTING");
        DbEntity floatTest = getDbEntity(map, "FLOAT_TEST");
        DbEntity smallintTest = getDbEntity(map, "SMALLINT_TEST");
        DbAttribute integerAttr = getDbAttribute(dbe, "PAINTING_ID");
        DbAttribute decimalAttr = getDbAttribute(dbe, "ESTIMATED_PRICE");
        DbAttribute varcharAttr = getDbAttribute(dbe, "PAINTING_TITLE");
        DbAttribute floatAttr = getDbAttribute(floatTest, "FLOAT_COL");
        DbAttribute smallintAttr = getDbAttribute(smallintTest, "SMALLINT_COL");

        // check decimal
        assertTrue(
                msgForTypeMismatch(Types.DECIMAL, decimalAttr),
                Types.DECIMAL == decimalAttr.getType()
                        || Types.NUMERIC == decimalAttr.getType());
        assertEquals(2, decimalAttr.getScale());

        // check varchar
        assertEquals(
                msgForTypeMismatch(Types.VARCHAR, varcharAttr),
                Types.VARCHAR,
                varcharAttr.getType());
        assertEquals(255, varcharAttr.getMaxLength());
        // check integer
        assertEquals(
                msgForTypeMismatch(Types.INTEGER, integerAttr),
                Types.INTEGER,
                integerAttr.getType());
        // check float
        assertTrue(msgForTypeMismatch(Types.FLOAT, floatAttr), Types.FLOAT == floatAttr
                .getType()
                || Types.DOUBLE == floatAttr.getType()
                || Types.REAL == floatAttr.getType());

        // check smallint
        assertTrue(
                msgForTypeMismatch(Types.SMALLINT, smallintAttr),
                Types.SMALLINT == smallintAttr.getType()
                        || Types.INTEGER == smallintAttr.getType());
    }

    public void checkAllDBEntities(DataMap map) {

        for (DbEntity origEnt : originalMap().getDbEntities()) {
            DbEntity newEnt = map.getDbEntity(origEnt.getName());
            for (DbAttribute origAttr : origEnt.getAttributes()) {
                DbAttribute newAttr = (DbAttribute) newEnt.getAttribute(origAttr
                        .getName());
                assertNotNull(
                        "No matching DbAttribute for '" + origAttr.getName(),
                        newAttr);
                assertEquals(
                        msgForTypeMismatch(origAttr, newAttr),
                        origAttr.getType(),
                        newAttr.getType());
                // length and precision doesn't have to be the same
                // it must be greater or equal
                assertTrue(origAttr.getMaxLength() <= newAttr.getMaxLength());
                assertTrue(origAttr.getScale() <= newAttr.getScale());
            }
        }
    }

    private String msgForTypeMismatch(DbAttribute origAttr, DbAttribute newAttr) {
        return msgForTypeMismatch(origAttr.getType(), newAttr);
    }

    private String msgForTypeMismatch(int origType, DbAttribute newAttr) {
        String nt = TypesMapping.getSqlNameByType(newAttr.getType());
        String ot = TypesMapping.getSqlNameByType(origType);
        return attrMismatch(newAttr.getName(), "expected type: <"
                + ot
                + ">, but was <"
                + nt
                + ">");
    }

    private String attrMismatch(String attrName, String msg) {
        StringBuffer buf = new StringBuffer();
        buf.append("[Error loading attribute '").append(attrName).append("': ").append(
                msg).append("]");
        return buf.toString();
    }
}
TOP

Related Classes of org.apache.cayenne.access.DbLoaderTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.