Package org.apache.ojb.odmg

Source Code of org.apache.ojb.odmg.ObjectImageTest$Book

package org.apache.ojb.odmg;

/* Copyright 2002-2005 The Apache Software Foundation
*
* 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.
*/

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Iterator;

import org.apache.commons.lang.SerializationUtils;
import org.apache.commons.lang.SystemUtils;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.ojb.broker.Identity;
import org.apache.ojb.broker.query.Criteria;
import org.apache.ojb.broker.query.Query;
import org.apache.ojb.broker.query.QueryFactory;
import org.apache.ojb.broker.core.proxy.CollectionProxy;
import org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl;
import org.apache.ojb.broker.core.proxy.CollectionProxyListener;
import org.apache.ojb.broker.core.proxy.IndirectionHandler;
import org.apache.ojb.broker.core.proxy.MaterializationListener;
import org.apache.ojb.broker.core.proxy.ProxyHelper;
import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
import org.apache.ojb.junit.ODMGTestCase;
import org.odmg.OQLQuery;
import org.odmg.Transaction;

/**
* Check the quality of object image comparison:
* - new referenced objects
* - deleted referenced objects
* - deleted referenced objects
* ...etc.
*
* Test cases for refactored odmg-api implementation. These tests asserts previously outstanding
* ODMG-issues and proxy object handling in the ODMG API.
*
* @author <a href="mailto:arminw@apache.org">Armin Waibel</a>
* @version $Id: ObjectImageTest.java,v 1.1.2.8 2005/12/13 18:18:25 arminw Exp $
*/
public class ObjectImageTest extends ODMGTestCase
{
    static final int NONE = ObjectReferenceDescriptor.CASCADE_NONE;
    static final int LINK = ObjectReferenceDescriptor.CASCADE_LINK;
    static final int OBJECT = ObjectReferenceDescriptor.CASCADE_OBJECT;
    static final String EOL = SystemUtils.LINE_SEPARATOR;

    public static void main(String[] args)
    {
        junit.textui.TestRunner.main(new String[]{ObjectImageTest.class.getName()});
    }

    public void testReplaceOneToOneReference() throws Exception
    {
        String prefix = "testReplaceOneToOneReference_" + System.currentTimeMillis();
        ojbChangeReferenceSetting(Book.class, "reviews", true, NONE, NONE, false);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        Book book = new Book(prefix, null, null);
        Publisher p_1 = new PublisherImpl(prefix);
        Publisher p_2 = new PublisherImpl(prefix + "_replaced");
        book.setPublisher(p_1);
        database.makePersistent(book);
        database.makePersistent(p_1);
        database.makePersistent(p_2);
        tx.commit();

        Integer book_version = book.getVersion();
        Integer p1_version = p_1.getVersion();
        Integer p2_version = p_2.getVersion();

        tx.begin();
        tx.lock(book, Transaction.WRITE);
        tx.lock(book.getPublisher(), Transaction.READ);
        tx.lock(p_2, Transaction.READ);
        book.setPublisher(p_2);
        tx.commit();

        assertEquals(book_version.intValue() + 1, book.getVersion().intValue());
        assertEquals(p1_version, p_1.getVersion());
        assertEquals(p2_version, p_2.getVersion());
    }

    public void testAddCollectionObjectToExistingObject() throws Exception
    {
        String prefix = "testAddCollectionObjectToExistingObject_" + System.currentTimeMillis();
        ojbChangeReferenceSetting(Book.class, "reviews", true, NONE, NONE, false);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        Book book = new Book(prefix, null, null);
        Review r1 = new Review(prefix + "_1");
        database.makePersistent(book);
        database.makePersistent(r1);
        tx.commit();

        Integer book_version = book.getVersion();
        Integer r_1_version = r1.getVersion();

        Review r2 = new Review(prefix + "_2");
        tx.begin();
        tx.lock(r1, Transaction.WRITE);
        tx.lock(book, Transaction.READ);
        book.addReview(r1);
        book.addReview(r2);
        database.makePersistent(r2);
        tx.commit();

        assertEquals(book_version, book.getVersion());
        assertTrue(book.getId() != null);

        Integer r_2_version = r2.getVersion();

        tx.begin();
        tx.getBroker().clearCache();
        Book loadedCopy = (Book) tx.getBroker().getObjectByIdentity(
                tx.getBroker().serviceIdentity().buildIdentity(Book.class, book.getId()));
        assertNotNull(loadedCopy);
        assertNotNull(loadedCopy.getReviews());
        assertEquals(2, loadedCopy.getReviews().size());
        assertEquals(book_version, loadedCopy.getVersion());
        Review new_r1 = (Review) loadedCopy.getReviews().get(0);
        Review new_r2 = (Review) loadedCopy.getReviews().get(1);
        assertEquals(r_1_version.intValue() + 1, new_r1.getVersion().intValue());
        assertEquals(r_2_version, new_r2.getVersion());

        tx.getBroker().clearCache();
        Criteria criteria = new Criteria();
        criteria.addLike("title", prefix);
        Query q = QueryFactory.newQuery(Book.class, criteria);
        Collection books = tx.getBroker().getCollectionByQuery(q);
        assertNotNull(books);
        assertEquals(1, books.size());
        Book new_book = (Book) books.iterator().next();
        tx.commit();
        assertEquals(book_version, new_book.getVersion());

        tx.begin();
        tx.lock(loadedCopy, Transaction.WRITE);
        Review removed = (Review) loadedCopy.getReviews().remove(0);
        Review stayed =  (Review) loadedCopy.getReviews().get(0);
        tx.commit();
        // expect same version, nothing should be changed
        assertEquals(r_2_version, stayed.getVersion());
        //
        //assertEquals(r_1_version, removed.getVersion());

        tx.begin();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(prefix);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        tx.commit();

        assertEquals(1, b.getReviews().size());
        Review r = (Review) b.getReviews().get(0);
        if(!r.equals(r1) && !r.equals(r2))
        {
            fail("Wrong object or wrong object version returned. Returned obj was "
                    + EOL + r + " expected object was " + EOL + r1 + " or " + EOL + r2);
        }
    }

    /**
     * test persistence by reachability of collection reference objects
     */
    public void testPersistenceByReachability_1() throws Exception
    {
        String name = "testPersistenceByReachability_1_" + System.currentTimeMillis();
        ojbChangeReferenceSetting(Book.class, "reviews", true, NONE, NONE, true);

        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Review r1 = new Review(name);
        Review r2 = new Review(name);
        Review r3 = new Review(name + "_not_persistent");
        ArrayList reviews = new ArrayList();
        reviews.add(r1);
        reviews.add(r2);
        reviews.add(r3);
        book.setReviews(reviews);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        Review r4 = new Review(name + "_new_added");
        // add a new review after make persistent main object
        book.addReview(r4);
        tx.setCascadingDelete(Book.class, true);
        // remove object after make persistent main object
        book.removeReview(r3);
        tx.commit();
        // System.err.println("## Insert main object with 3 referecnes");

        tx.begin();
        tx.getBroker().clearCache();

        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        assertNotNull(b.getReviews());
        assertEquals(3, b.getReviews().size());

        query = odmg.newOQLQuery();
        query.create("select reviews from " + Review.class.getName() + " where summary like $1");
        query.bind(name + "_new_added");
        result = (Collection) query.execute();
        // we expect the delayed added Review object
        assertEquals(1, result.size());

        query = odmg.newOQLQuery();
        query.create("select reviews from " + Review.class.getName() + " where summary like $1");
        query.bind(name + "_not_persistent");
        result = (Collection) query.execute();
        // we expect the removed Review object wasn't persistet
        assertEquals(0, result.size());
        tx.commit();
    }

    /**
     * test persistence by reachability of collection reference objects
     */
    public void testPersistenceByReachability_2() throws Exception
    {
        String name = "testPersistenceByReachability_2_" + System.currentTimeMillis();
        ojbChangeReferenceSetting(Book.class, "reviews", true, NONE, NONE, true);

        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Review r1 = new Review(name);
        Review r2 = new Review(name);
        Review r3 = new Review(name + "_not_persistent");
        ArrayList reviews = new ArrayList();
        reviews.add(r1);
        reviews.add(r2);
        reviews.add(r3);
        book.setReviews(reviews);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        Review r4 = new Review(name + "_new_added");
        // add a new review after make persistent main object
        book.addReview(r4);
        tx.setCascadingDelete(Book.class, true);
        // remove object after make persistent main object
        book.removeReview(r3);
        tx.checkpoint();

        //tx.begin();
        tx.getBroker().clearCache();

        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        assertNotNull(b.getReviews());
        assertEquals(3, b.getReviews().size());

        query = odmg.newOQLQuery();
        query.create("select reviews from " + Review.class.getName() + " where summary like $1");
        query.bind(name + "_new_added%");
        result = (Collection) query.execute();
        // we expect the delayed added Review object
        assertEquals(1, result.size());

        query = odmg.newOQLQuery();
        query.create("select reviews from " + Review.class.getName() + " where summary like $1");
        query.bind(name + "_not_persistent");
        result = (Collection) query.execute();
        // we expect the removed Review object wasn't persistet
        assertEquals(0, result.size());

        b.setTitle(name + "_updated");
        tx.commit();

        query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name + "_updated");
        result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b_updated = (Book) result.iterator().next();
        assertNotNull(b_updated.getReviews());
        assertEquals(3, b_updated.getReviews().size());
        assertEquals(name+"_updated", b_updated.getTitle());
    }

    public void testAddPersistentObjectTo1toN() throws Exception
    {
        String name = "testAddPersistentObjectTo1toN_" + System.currentTimeMillis();
        Review review = new Review(name);
        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(review);
        tx.commit();

        Integer versionReview = review.getVersion();

        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        // tx.lock(review, Transaction.WRITE);
        database.makePersistent(book);
        book.addReview(review);
        tx.commit();

        // the Review object has to be linked
        assertEquals("expect that this object was updated", versionReview.intValue() + 1, review.getVersion().intValue());

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        assertNotNull(b.getReviews());
        assertEquals(1, b.getReviews().size());
        tx.commit();
    }

    public void testAddPersistentObjectToMtoN() throws Exception
    {
        String name = "testAddPersistentObjectToMtoN_" + System.currentTimeMillis();
        Author author = new Author(name, null);
        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(author);
        tx.commit();

        Integer versionReview = author.getVersion();

        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        book.addAuthor(author);
        author.addBook(book);
        tx.commit();

        // the Review object has to be linked
        assertEquals("expect that this object wasn't updated", versionReview.intValue(), author.getVersion().intValue());

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        assertNotNull(b.getAuthors());
        assertEquals(1, b.getAuthors().size());
        tx.commit();
    }

    /**
     * only lock object, no changes made
     */
    public void testChangeMainFields() throws Exception
    {
        String name = "testChangeMainFields_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();

        Integer version = book.getVersion();
        // System.err.println("### 1. commit, insert new object");

        tx.begin();
        tx.lock(book, Transaction.WRITE);
        tx.commit();

        // System.err.println("### 2. commit, no changes");
        assertEquals(version, book.getVersion());

        tx.begin();
        tx.lock(book, Transaction.WRITE);
        // we set the same date, so no reason to update
        book.setPublicationDate(new Date(date.getTime()));
        tx.commit();

        // System.err.println("### 3. commit, replace with same date");
        assertEquals(version, book.getVersion());

        tx.begin();
        tx.lock(book, Transaction.WRITE);
        // now we change the date
        Date d = new Date(1111);
        book.setPublicationDate(d);
        tx.commit();
        // System.err.println("### 4. commit, changed date");
        assertFalse(date.equals(book.getPublicationDate()));
        assertFalse(version.equals(book.getVersion()));
    }

    /**
     * modify field of main object
     */
    public void testChangeMainFields_2() throws Exception
    {
        String name = "testChangeMainFields_2_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();

        Integer version = book.getVersion();

        tx.begin();
        tx.lock(book, Transaction.WRITE);
        book.setCover(new byte[]{2,3,4,5,6,7,8,8});
        tx.commit();

        assertFalse(version.equals(book.getVersion()));
        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        assertFalse(version.equals(b.getVersion()));
        tx.commit();
    }

    /**
     * lock object and lock serialized unmodified version again
     */
    public void testChangeMainFields_3() throws Exception
    {
        String name = "testChangeMainFields_3_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();

        Integer version = book.getVersion();

        tx.begin();
        tx.lock(book, Transaction.WRITE);
        book = (Book) SerializationUtils.clone(book);
        tx.lock(book, Transaction.WRITE);
        tx.commit();

        assertEquals(version, book.getVersion());
    }

    /**
     * Double lock object with reference
     */
    public void testChangeOneToOneReference_1() throws Exception
    {
        String name = "testChangeOneToOneReference_1_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Publisher publisher = new PublisherImpl(name);
        book.setPublisher(publisher);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();
        // System.err.println("### 1. commit, insert new object");

        Integer versionBook = book.getVersion();
        Integer versionPublisher = book.getPublisher().getVersion();

        tx.begin();
        tx.lock(book, Transaction.WRITE);
        tx.lock(book, Transaction.WRITE);
        tx.commit();
        // System.err.println("### 2. commit, double lock call, no changes");

        assertEquals(versionBook, book.getVersion());
        assertEquals(versionPublisher, book.getVersion());
    }

    /**
     * Double lock object with reference and proxy reference
     */
    public void testChangeOneToOneReference_1b() throws Exception
    {
        String name = "testChangeOneToOneReference_1b_" + System.currentTimeMillis();
        ojbChangeReferenceSetting(Book.class, "publisher", true, NONE, NONE, true);

        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Publisher publisher = new PublisherImpl(name);
        book.setPublisher(publisher);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();
        // System.err.println("### 1. commit, insert new object");

        Integer versionBook = book.getVersion();
        Integer versionPublisher = book.getPublisher().getVersion();

        tx.begin();
        tx.lock(book, Transaction.WRITE);
        tx.lock(book, Transaction.WRITE);
        tx.commit();
        // System.err.println("### 2. commit, double lock call, no changes");

        assertEquals(versionBook, book.getVersion());
        assertEquals(versionPublisher, book.getVersion());
    }

    /**
     * lock object with reference and lock serialized version again
     */
    public void testChangeOneToOneReference_2() throws Exception
    {
        String name = "testChangeOneToOneReference_2_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Publisher publisher = new PublisherImpl(name);
        book.setPublisher(publisher);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();
        // System.err.println("### 1. commit, insert new object");

        Integer versionBook = book.getVersion();
        Integer versionPublisher = book.getPublisher().getVersion();

        tx.begin();
        tx.lock(book, Transaction.WRITE);
        // nothing changed, so no need to update objects
        book = (Book) SerializationUtils.clone(book);
        tx.lock(book, Transaction.WRITE);
        tx.commit();

        assertEquals(versionBook, book.getVersion());
        assertEquals(versionPublisher, book.getVersion());
    }

    /**
     * lock object with reference, change reference only
     */
    public void testChangeOneToOneReference_3() throws Exception
    {
        String name = "testChangeOneToOneReference_2_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Publisher publisher = new PublisherImpl(name);
        book.setPublisher(publisher);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();
        // System.err.println("### 1. commit, insert new object");

        Integer versionBook = book.getVersion();
        Integer versionPublisher = book.getPublisher().getVersion();

        tx.begin();
        tx.lock(book, Transaction.WRITE);
        // nothing changed, so no need to update objects
        book = (Book) SerializationUtils.clone(book);
        Publisher p = book.getPublisher();
        p.setName(name + "_updated");
        // not needed to re-lock, because nothing changed, but
        // if we lock Book no update should be done, because nothing changed
        tx.lock(book, Transaction.WRITE);
        // we have to re-lock the changed objects, because it was serialized
        tx.lock(p, Transaction.WRITE);
        tx.commit();

        // no changes made in Book
        assertEquals(versionBook, book.getVersion());
        // publisher should be updated
        assertEquals(new Integer(versionPublisher.intValue() + 1), p.getVersion());
    }

    /**
     * lock object with reference, replace reference only
     */
    public void testReplaceOneToOneReference_1() throws Exception
    {
        String name = "testChangeOneToOneReference_2_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Publisher publisher = new PublisherImpl(name);
        book.setPublisher(publisher);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();
        // System.err.println("### 1. commit, insert new object");

        Integer versionBook = book.getVersion();
        Integer versionPublisher = book.getPublisher().getVersion();

        tx.begin();
        tx.lock(book, Transaction.WRITE);
        Publisher p = new PublisherImpl(name + "_new");
        // set new Publisher instance
        book.setPublisher(p);
        tx.lock(p, Transaction.WRITE);
        tx.commit();

        // changes made in Book
        assertEquals(new Integer(versionBook.intValue() + 1), book.getVersion());
        // publisher should not be updated, because it was replaced
        assertEquals(versionPublisher, p.getVersion());
    }

    /**
     * lock object with reference, replace reference only
     */
    public void testReplaceOneToOneReference_2() throws Exception
    {
        String name = "testChangeOneToOneReference_2_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Publisher publisher = new PublisherImpl(name);
        book.setPublisher(publisher);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();
        // System.err.println("### 1. commit, insert new object");

        Integer versionBook = book.getVersion();
        Integer versionPublisher = book.getPublisher().getVersion();

        tx.begin();
        tx.lock(book, Transaction.WRITE);
        book = (Book) SerializationUtils.clone(book);
        Publisher p = new PublisherImpl(name + "_new");
        // set new Publisher instance
        book.setPublisher(p);
        // not needed to re-lock, because nothing changed, but
        // if we lock Book no update should be done, because nothing changed
        tx.lock(book, Transaction.WRITE);
        // we have to re-lock the changed objects, because it was serialized
        tx.lock(p, Transaction.WRITE);
        tx.commit();

        // changes made in Book
        assertEquals(new Integer(versionBook.intValue() + 1), book.getVersion());
        // publisher should not be updated, because it was replaced
        assertEquals(versionPublisher, p.getVersion());
    }

    /**
     * check materialization of proxy object
     */
    public void testChangeOneToOneReference_4() throws Exception
    {
        ojbChangeReferenceSetting(Book.class, "publisher", true, NONE, NONE, true);
        String name = "testChangeOneToOneReference_4_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Publisher publisher = new PublisherImpl(name);
        book.setPublisher(publisher);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();

        Integer versionBook = book.getVersion();

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        IndirectionHandler handler = ProxyHelper.getIndirectionHandler(b.getPublisher());
        assertNotNull(handler);
        assertFalse(handler.alreadyMaterialized());
        handler.addListener(
                new MaterializationListener()
                {
                    public void beforeMaterialization(IndirectionHandler handler, Identity oid)
                    {
                        fail("Reference shall not materialize while locking");
                    }

                    public void afterMaterialization(IndirectionHandler handler, Object materializedObject)
                    {
                    }
                }
        );
        tx.lock(b, Transaction.WRITE);
        tx.commit();

        assertEquals(versionBook, b.getVersion());
    }

    /**
     * replace proxy reference by new reference object
     */
    public void testChangeOneToOneReference_5() throws Exception
    {
        ojbChangeReferenceSetting(Book.class, "publisher", true, NONE, NONE, true);
        String name = "testChangeOneToOneReference_5_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Publisher publisher = new PublisherImpl(name);
        book.setPublisher(publisher);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();
        // System.err.println("### 1. commit, insert new object");


        Integer versionBook = book.getVersion();

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        IndirectionHandler handler = ProxyHelper.getIndirectionHandler(b.getPublisher());
        assertNotNull(handler);
        assertFalse(handler.alreadyMaterialized());
        handler.addListener(
                new MaterializationListener()
                {
                    public void beforeMaterialization(IndirectionHandler handler, Identity oid)
                    {
                        fail("Reference shall not materialize while locking");
                    }

                    public void afterMaterialization(IndirectionHandler handler, Object materializedObject)
                    {
                    }
                }
        );
        // no need to lock with default settings, because lock is done when query object
        tx.lock(b, Transaction.WRITE);
        // replace 1:1 reference
        Publisher p = new PublisherImpl(name+"_new");
        b.setPublisher(p);
        //tx.lock(p, Transaction.WRITE);
        tx.commit();

        // we expect increased version, because Book object needs update - changed FK
        assertEquals(new Integer(versionBook.intValue() + 1), b.getVersion());
        // should should differ, because new reference should be stored
        assertFalse(publisher.getName().equals(p.getName()));
        assertNotNull(p.getVersion());

        tx.begin();
        tx.getBroker().clearCache();
        query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        result = (Collection) query.execute();
        tx.commit();
        assertEquals(1, result.size());
        b = (Book) result.iterator().next();
        Publisher newP = b.getPublisher();
        assertNotNull(newP);
        assertEquals(name+"_new", newP.getName());
    }

    /**
     * update referenced object
     */
    public void testChangeOneToOneReference_6() throws Exception
    {
        String name = "testChangeOneToOneReference_6_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Publisher publisher = new PublisherImpl(name);
        book.setPublisher(publisher);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();

        Integer versionBook = book.getVersion();
        Integer versionPublisher = book.getPublisher().getVersion();

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        tx.lock(b, Transaction.WRITE);
        b.getPublisher().setName("updated_" + b.getPublisher().getName());
        tx.commit();

        // nothing changed
        assertEquals(versionBook, b.getVersion());
        // version should should differ, because reference should be updated
        assertFalse(versionPublisher.equals(b.getPublisher().getVersion()));
        assertEquals("updated_" + name, b.getPublisher().getName());
    }

    /**
     * add new reference
     */
    public void testChangeOneToOneReference_7() throws Exception
    {
        String name = "testChangeOneToOneReference_7_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();

        Integer versionBook = book.getVersion();

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();

        tx.lock(b, Transaction.WRITE);
        assertNull(b.getPublisher());
        Publisher publisher = new PublisherImpl(name);
        b.setPublisher(publisher);
        // tx.lock(publisher, Transaction.WRITE);
        tx.commit();

        tx.begin();
        tx.getBroker().clearCache();
        query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        result = (Collection) query.execute();
        assertEquals(1, result.size());
        b = (Book) result.iterator().next();
        tx.commit();

        // we expect increased version, because Book object needs update
        assertEquals(new Integer(versionBook.intValue() + 1), b.getVersion());
        // version should differ from null, because new reference should be stored
        assertNotNull(b.getPublisher());
        assertNotNull(b.getPublisher().getVersion());
        assertEquals(name, b.getPublisher().getName());
    }

    /**
     * remove reference
     */
    public void testChangeOneToOneReference_8() throws Exception
    {
        String name = "testChangeOneToOneReference_8_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Publisher publisher = new PublisherImpl(name);
        book.setPublisher(publisher);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();

        Integer versionBook = book.getVersion();
        Integer versionPublisher = book.getPublisher().getVersion();

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();

        tx.lock(b, Transaction.WRITE);
        b.setPublisher(null);
        tx.commit();

        tx.begin();
        tx.getBroker().clearCache();
        query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        result = (Collection) query.execute();
        assertEquals(1, result.size());
        b = (Book) result.iterator().next();
        tx.commit();

        // we expect increased version, because Book object needs update
        assertEquals(new Integer(versionBook.intValue() + 1), b.getVersion());
        assertNull(b.getPublisher());

        tx.begin();
        tx.getBroker().clearCache();
        query = odmg.newOQLQuery();
        query.create("select publishers from " + Publisher.class.getName() + " where name like $1");
        query.bind(name);
        result = (Collection) query.execute();
        // we don't remove the reference object
        assertEquals(1, result.size());
        Publisher p = (Publisher) result.iterator().next();
        assertEquals(name, p.getName());
        // removed 1:1 reference, expect unchanged version
        assertEquals(versionPublisher, p.getVersion());
        tx.commit();
    }

    /**
     * delete reference
     */
    public void testChangeOneToOneReference_8b() throws Exception
    {
        String name = "testChangeOneToOneReference_8b_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Publisher publisher = new PublisherImpl(name);
        book.setPublisher(publisher);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();

        Integer versionBook = book.getVersion();

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();

        tx.lock(b, Transaction.WRITE);
        database.deletePersistent(b.getPublisher());
        b.setPublisher(null);
        tx.commit();

        tx.begin();
        tx.getBroker().clearCache();
        query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        result = (Collection) query.execute();
        assertEquals(1, result.size());
        b = (Book) result.iterator().next();
        tx.commit();

        // we expect increased version, because Book object needs update
        assertEquals(new Integer(versionBook.intValue() + 1), b.getVersion());
        assertNull(b.getPublisher());

        tx.begin();
        tx.getBroker().clearCache();
        query = odmg.newOQLQuery();
        query.create("select publishers from " + Publisher.class.getName() + " where name like $1");
        query.bind(name);
        result = (Collection) query.execute();
        // we don't remove the reference object
        assertEquals(0, result.size());
        tx.commit();
    }

    /**
     * check materialzation of collection reference
     */
    public void testCollectionReference_1() throws Exception
    {
        String name = "testCollectionReference_1_" + System.currentTimeMillis();
        ojbChangeReferenceSetting(Book.class, "reviews", true, NONE, NONE, true);

        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Review r1 = new Review(name);
        Review r2 = new Review(name);
        Review r3 = new Review(name);
        ArrayList reviews = new ArrayList();
        reviews.add(r1);
        reviews.add(r2);
        reviews.add(r3);
        book.setReviews(reviews);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();
        // System.err.println("## Insert main object with 3 referecnes");

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        CollectionProxy handler = ProxyHelper.getCollectionProxy(b.getReviews());
        assertFalse("Don't expect an materialized collection proxy", handler.isLoaded());
        handler.addListener(new CollectionProxyListener()
        {
            public void beforeLoading(CollectionProxyDefaultImpl colProxy)
            {
                fail("Collection proxy shouldn't be materialized");
            }

            public void afterLoading(CollectionProxyDefaultImpl colProxy)
            {
            }
        });
        assertNotNull(b.getReviews());
        assertEquals(3, b.getReviews().size());

        tx.lock(b, Transaction.WRITE);
        tx.commit();
    }

    /**
     * update collection reference object
     */
    public void testCollectionReference_2a() throws Exception
    {
        String name = "testCollectionReference_2a_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Review r1 = new Review(name);
        Review r2 = new Review(name);
        Review r3 = new Review(name);
        ArrayList reviews = new ArrayList();
        reviews.add(r1);
        reviews.add(r2);
        reviews.add(r3);
        book.setReviews(reviews);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();
        // System.err.println("## Insert main object with 3 referecnes");

        Integer versionBook = book.getVersion();
        Integer versionR1 = ((Review) book.getReviews().get(0)).getVersion();

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        assertEquals(versionBook, b.getVersion());
        assertNotNull(b.getReviews());
        assertEquals(3, b.getReviews().size());

        tx.lock(b, Transaction.WRITE);
        Review newR2 = (Review) b.getReviews().get(1);
        newR2.setSummary("updated" + name);
        final int newR2id = newR2.getId().intValue();
        tx.commit();

        assertEquals(versionBook, b.getVersion());
        // this referenced object was not updated
        Integer versionR1New = ((Review) b.getReviews().get(0)).getVersion();
        assertEquals(versionR1, versionR1New);

        tx.begin();
        tx.getBroker().clearCache();
        query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        result = (Collection) query.execute();
        assertEquals(1, result.size());
        b = (Book) result.iterator().next();
        assertNotNull(b.getReviews());
        assertEquals(3, b.getReviews().size());

        // Search for the updated R2:
        final List updatedReviews = b.getReviews();
        for (int i = 0; i < updatedReviews.size(); i++)
        {
            newR2 = (Review) updatedReviews.get(i);
            if (newR2id == newR2.getId().intValue()) {
                break;
            }
        }
        assertEquals("Could not find the updated review in the returned results",
                newR2id, newR2.getId().intValue());
        assertEquals("updated" + name, newR2.getSummary());
        assertEquals(versionBook, b.getVersion());
        // this referenced object was not updated
        versionR1New = ((Review) b.getReviews().get(0)).getVersion();
        assertEquals(versionR1, versionR1New);
    }

    /**
     * update proxy collection reference object
     */
    public void testCollectionReference_2b() throws Exception
    {
        String name = "testCollectionReference_2b_" + System.currentTimeMillis();

        ojbChangeReferenceSetting(Book.class, "reviews", true, NONE, NONE, true);

        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Review r1 = new Review(name);
        Review r2 = new Review(name);
        Review r3 = new Review(name);
        ArrayList reviews = new ArrayList();
        reviews.add(r1);
        reviews.add(r2);
        reviews.add(r3);
        book.setReviews(reviews);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();
        // System.err.println("## Insert main object with 3 referecnes");

        Integer versionBook = book.getVersion();
        Integer versionR0 = ((Review) book.getReviews().get(0)).getVersion();
        Integer versionR1 = ((Review) book.getReviews().get(1)).getVersion();

        tx.begin();
        tx.getBroker().clearCache();
        // System.err.println("## Started new tx");
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        assertEquals(versionBook, b.getVersion());
        assertNotNull(b.getReviews());
        assertEquals(3, b.getReviews().size());
        assertEquals(versionR0, ((Review) b.getReviews().get(0)).getVersion());
        assertEquals(versionR1, ((Review) b.getReviews().get(1)).getVersion());

        // System.err.println("## Query done");
        tx.lock(b, Transaction.WRITE);
        // System.err.println("## Lock object again");
        Review newR1 = (Review) b.getReviews().get(1);
        newR1.setSummary("updated" + name);
        // System.err.println("## Before commit");
        tx.commit();
        // System.err.println("## Commit Book with updated Review");

        assertEquals(versionBook, b.getVersion());
        assertEquals(3, b.getReviews().size());

        // the updated one
        Integer versionR1New = ((Review) b.getReviews().get(1)).getVersion();
        assertEquals(new Integer(versionR1.intValue() + 1), versionR1New);
        // this referenced object was not updated
        Integer versionR0New = ((Review) b.getReviews().get(0)).getVersion();
        assertEquals(versionR0, versionR0New);

        tx.begin();
        tx.getBroker().clearCache();
        query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        result = (Collection) query.execute();
        assertEquals(1, result.size());
        b = (Book) result.iterator().next();
        assertNotNull(b.getReviews());
        assertEquals(3, b.getReviews().size());
        tx.commit();

        // query for updated Review
        tx.begin();
        tx.getBroker().clearCache();
        query = odmg.newOQLQuery();
        query.create("select reviews from " + Review.class.getName() + " where summary like $1");
        query.bind("updated" + name);
        result = (Collection) query.execute();
        tx.commit();
        // the update Review object
        assertEquals(1, result.size());
        // query for unchanged Review objects
        tx.begin();
        tx.getBroker().clearCache();
        query = odmg.newOQLQuery();
        query.create("select reviews from " + Review.class.getName() + " where summary like $1");
        query.bind(name);
        result = (Collection) query.execute();
        tx.commit();

        assertEquals(2, result.size());
        assertEquals(versionR0, ((Review) new ArrayList(result).get(0)).getVersion());

    }

    /**
     * remove collection reference object
     * this test expects that removed 1:n referenced objects only
     * be "unlinked" instead of deleted.
     */
    public void testCollectionReference_3() throws Exception
    {
        String name = "testCollectionReference_3_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Review r1 = new Review(name);
        ArrayList reviews = new ArrayList();
        reviews.add(r1);
        book.setReviews(reviews);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();

        Integer versionBook = book.getVersion();
        Integer versionR1 = ((Review) book.getReviews().get(0)).getVersion();

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        assertEquals(versionBook, b.getVersion());
        assertNotNull(b.getReviews());
        assertEquals(1, b.getReviews().size());

        //***********************************
        tx.lock(b, Transaction.WRITE);
        // remove from collection, but do not explicit delete
        tx.setCascadingDelete(Book.class, "reviews", false);
        Review newR1 = (Review) b.getReviews().remove(0);
        tx.commit();
        //***********************************

        // only the removed reference has changed
        assertEquals(versionBook, b.getVersion());
        // expect an "unlinked" new version
        assertEquals(new Integer(versionR1.intValue() + 1), newR1.getVersion());

        tx.begin();
        tx.getBroker().clearCache();
        query = odmg.newOQLQuery();
        query.create("select reviews from " + Review.class.getName() + " where summary like $1");
        query.bind(name);
        result = (Collection) query.execute();
        tx.commit();

        // we don't delete the Review object, only remove from reference collection
        assertEquals(1, result.size());
        Review r = (Review) result.iterator().next();
        // expect new object version, because the FK to main object was set null
        assertEquals(new Integer(versionR1.intValue() + 1), r.getVersion());

        tx.begin();
        query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        result = (Collection) query.execute();
        tx.commit();

        assertEquals(1, result.size());
        b = (Book) result.iterator().next();
        assertEquals(versionBook, b.getVersion());
        // we have removed the Review object
        assertEquals(0, b.getReviews().size());
    }

    /**
     * remove collection reference object and explicit delete it
     */
    public void testCollectionReference_3b() throws Exception
    {
        String name = "testCollectionReference_3b_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Review r1 = new Review(name);
        ArrayList reviews = new ArrayList();
        reviews.add(r1);
        book.setReviews(reviews);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();

        Integer versionBook = book.getVersion();

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        assertEquals(versionBook, b.getVersion());
        assertNotNull(b.getReviews());
        assertEquals(1, b.getReviews().size());

        tx.lock(b, Transaction.WRITE);
        // remove from collection and delete
        Review newR1 = (Review) b.getReviews().remove(0);
        database.deletePersistent(newR1);
        tx.commit();

        // only the removed reference has changed
        assertEquals(versionBook, b.getVersion());

        tx.begin();
        query = odmg.newOQLQuery();
        query.create("select reviews from " + Review.class.getName() + " where summary like $1");
        query.bind(name);
        result = (Collection) query.execute();
        tx.commit();

        assertEquals(0, result.size());

        tx.begin();
        query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        result = (Collection) query.execute();
        tx.commit();

        assertEquals(1, result.size());
        b = (Book) result.iterator().next();
        assertEquals(versionBook, b.getVersion());
        assertEquals(0, b.getReviews().size());
    }

    /**
     * remove collection reference object with enabled auto-delete
     */
    public void testCollectionReference_3c() throws Exception
    {
        String name = "testCollectionReference_3c_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Review r1 = new Review(name);
        ArrayList reviews = new ArrayList();
        reviews.add(r1);
        book.setReviews(reviews);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();

        Integer versionBook = book.getVersion();

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        assertEquals(versionBook, b.getVersion());
        assertNotNull(b.getReviews());
        assertEquals(1, b.getReviews().size());

        tx.lock(b, Transaction.WRITE);
        tx.setCascadingDelete(Book.class, "reviews", true);
        // remove from collection with cascading delete
        b.getReviews().remove(0);
        tx.commit();

        // only the removed reference has changed
        assertEquals(versionBook, b.getVersion());

        tx.begin();
        tx.getBroker().clearCache();
        query = odmg.newOQLQuery();
        query.create("select reviews from " + Review.class.getName() + " where summary like $1");
        query.bind(name);
        result = (Collection) query.execute();
        tx.commit();

        // cascading delete was used, so we don't expect an unlinked
        // version of the Review class
        assertEquals(0, result.size());


        tx.begin();
        query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        result = (Collection) query.execute();
        tx.commit();

        assertEquals(1, result.size());
        b = (Book) result.iterator().next();
        assertEquals(versionBook, b.getVersion());
        // we have removed the Review object
        assertEquals(0, b.getReviews().size());
    }

    /**
     * delete Book object with existing references
     */
    public void testCollectionReference_4a() throws Exception
    {
        String name = "testCollectionReference_4_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Review r1 = new Review(name);
        Review r2 = new Review(name);
        Review r3 = new Review(name);
        Author a1 = new Author(name, null);
        Author a2 = new Author(name, null);
        r1.setAuthor(a1);
        r2.setAuthor(a1);
        r3.setAuthor(a2);
        ArrayList reviews = new ArrayList();
        reviews.add(r1);
        reviews.add(r2);
        reviews.add(r3);
        book.setReviews(reviews);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();

        Integer versionBook = book.getVersion();

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        assertEquals(versionBook, b.getVersion());
        assertNotNull(b.getReviews());
        assertEquals(3, b.getReviews().size());
        assertNotNull(((Review) b.getReviews().get(0)).getAuthor());
        assertNotNull(((Review) b.getReviews().get(1)).getAuthor());
        assertNotNull(((Review) b.getReviews().get(2)).getAuthor());

        // Book instance should be already locked
        // now mark Book for delete and disable cascading delete
        // for the 1:n relation to Review class
        tx.setCascadingDelete(Book.class, "reviews", false);
        database.deletePersistent(b);
        tx.commit();
        // System.out.println("## After commit");

        tx.begin();
        tx.getBroker().clearCache();
        query = odmg.newOQLQuery();
        query.create("select reviews from " + Review.class.getName() + " where summary like $1");
        query.bind(name);
        result = (Collection) query.execute();
        tx.commit();
        // we auto-delete the Review object, only remove from reference collection
        assertEquals(3, result.size());
        List list = new ArrayList(result);
        assertNotNull(((Review) list.get(0)).getAuthor());
        assertNotNull(((Review) list.get(1)).getAuthor());
        assertNotNull(((Review) list.get(2)).getAuthor());
        Review newR1 = (Review) list.get(0);
        // book was deleted so we expect unlink of FK
        assertNull(newR1.getFkBook());


        tx.begin();
        query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        result = (Collection) query.execute();
        tx.commit();
        assertEquals(0, result.size());
    }

    /**
     * delete Book object with existing references and circular referencing objects
     */
    public void testCollectionReference_4b() throws Exception
    {
        String name = "testCollectionReference_4_" + System.currentTimeMillis();
        Date date = new Date();
        byte[] cover = new byte[]{2,3,4,5,6,7,8,9};
        Book book = new Book(name, date, cover);
        Review r1 = new Review(name);
        Review r2 = new Review(name);
        Review r3 = new Review(name);
        Author a1 = new Author(name, null);
        Author a2 = new Author(name, null);
        r1.setAuthor(a1);
        r2.setAuthor(a1);
        r3.setAuthor(a2);
        ArrayList reviews = new ArrayList();
        reviews.add(r1);
        reviews.add(r2);
        reviews.add(r3);
        book.setReviews(reviews);
        ArrayList authors = new ArrayList();
        authors.add(a1);
        authors.add(a2);
        book.setAuthors(authors);

        TransactionExt tx = (TransactionExt) odmg.newTransaction();
        tx.begin();
        database.makePersistent(book);
        tx.commit();

        Integer versionBook = book.getVersion();

        tx.begin();
        tx.getBroker().clearCache();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        Collection result = (Collection) query.execute();
        assertEquals(1, result.size());
        Book b = (Book) result.iterator().next();
        assertEquals(versionBook, b.getVersion());
        assertNotNull(b.getReviews());
        assertEquals(3, b.getReviews().size());
        assertNotNull(((Review) b.getReviews().get(0)).getAuthor());
        assertNotNull(((Review) b.getReviews().get(1)).getAuthor());
        assertNotNull(((Review) b.getReviews().get(2)).getAuthor());
        assertNotNull(b.getAuthors());
        assertEquals(2, b.getAuthors().size());
        Author newA = (Author) b.getAuthors().get(0);
        boolean failed = true;
        for(Iterator iterator = b.getReviews().iterator(); iterator.hasNext();)
        {
            Review review =  (Review) iterator.next();
            if(newA.equals(review.getAuthor()))
            {
                // as we have circular references we expect the same object instance
                assertSame(newA, review.getAuthor());
                failed = false;
            }
        }
        if(failed) fail("Expect the same object instance, but not found for " + newA);

        // Book instance should be already locked
        // now mark Book for delete and disable cascading delete
        // for the 1:n relation to Review class
        tx.setCascadingDelete(Book.class, "reviews", false);
        database.deletePersistent(b);
        tx.commit();

        tx.begin();
        tx.getBroker().clearCache();
        query = odmg.newOQLQuery();
        query.create("select reviews from " + Review.class.getName() + " where summary like $1");
        query.bind(name);
        result = (Collection) query.execute();
        tx.commit();
        // we auto-delete the Review object, only remove from reference collection
        assertEquals(3, result.size());
        List list = new ArrayList(result);
        assertNotNull(((Review) list.get(0)).getAuthor());
        assertNotNull(((Review) list.get(1)).getAuthor());
        assertNotNull(((Review) list.get(2)).getAuthor());
        Review newR1 = (Review) list.get(0);
        // book was deleted so we expect unlink of FK
        assertNull(newR1.getFkBook());
        newA = ((Review) list.get(0)).getAuthor();
        assertEquals(0, newA.getBooks().size());


        tx.begin();
        query = odmg.newOQLQuery();
        query.create("select books from " + Book.class.getName() + " where title like $1");
        query.bind(name);
        result = (Collection) query.execute();
        tx.commit();
        assertEquals(0, result.size());
    }

    //=======================================================
    // inner test classes
    //=======================================================
    public static final class Book implements Serializable
    {
        private Integer id;
        private String title;
        private Date publicationDate;
        private byte[] cover;
        private Integer version;

        private List authors;
        private List reviews;
        private Publisher publisher;

        public Book()
        {
        }

        public Book(String title, Date publicationDate, byte[] cover)
        {
            this.title = title;
            this.publicationDate = publicationDate;
            this.cover = cover;
        }

        public void addAuthor(Author author)
        {
            if(authors == null)
            {
                authors = new ArrayList();
            }
            authors.add(author);
        }

        public void addReview(Review review)
        {
            if(reviews == null)
            {
                reviews = new ArrayList();
            }
            reviews.add(review);
        }

        public boolean removeReview(Review review)
        {
            if(reviews != null) return reviews.remove(review);
            else return false;
        }

        public Integer getId()
        {
            return id;
        }

        public void setId(Integer id)
        {
            this.id = id;
        }

        public String getTitle()
        {
            return title;
        }

        public void setTitle(String title)
        {
            this.title = title;
        }

        public Date getPublicationDate()
        {
            return publicationDate;
        }

        public void setPublicationDate(Date publicationDate)
        {
            this.publicationDate = publicationDate;
        }

        public byte[] getCover()
        {
            return cover;
        }

        public void setCover(byte[] cover)
        {
            this.cover = cover;
        }

        public Integer getVersion()
        {
            return version;
        }

        public void setVersion(Integer version)
        {
            this.version = version;
        }

        public List getAuthors()
        {
            return authors;
        }

        public void setAuthors(List authors)
        {
            this.authors = authors;
        }

        public List getReviews()
        {
            return reviews;
        }

        public void setReviews(List reviews)
        {
            this.reviews = reviews;
        }

        public Publisher getPublisher()
        {
            return publisher;
        }

        public void setPublisher(Publisher publisher)
        {
            this.publisher = publisher;
        }
    }

    public static final class Author implements Serializable
    {
        private Integer id;
        private String name;
        private List books;
        private Integer version;

        public Author()
        {
        }

        public Author(String name, List books)
        {
            this.name = name;
            this.books = books;
        }

        public void addBook(Book book)
        {
            if(books == null)
            {
                books = new ArrayList();
            }
            books.add(book);
        }

        public Integer getId()
        {
            return id;
        }

        public void setId(Integer id)
        {
            this.id = id;
        }

        public String getName()
        {
            return name;
        }

        public void setName(String name)
        {
            this.name = name;
        }

        public List getBooks()
        {
            return books;
        }

        public void setBooks(List books)
        {
            this.books = books;
        }

        public Integer getVersion()
        {
            return version;
        }

        public void setVersion(Integer version)
        {
            this.version = version;
        }
    }

    public static interface Publisher extends Serializable
    {
        public Integer getId();
        public void setId(Integer id);
        public String getName();
        public void setName(String name);
        public Integer getVersion();
        public void setVersion(Integer version);
    }

    public static final class PublisherImpl implements Publisher
    {
        private Integer id;
        private String name;
        private Integer version;

        public PublisherImpl()
        {
        }

        public PublisherImpl(String name)
        {
            this.name = name;
        }

        public Integer getId()
        {
            return id;
        }

        public void setId(Integer id)
        {
            this.id = id;
        }

        public String getName()
        {
            return name;
        }

        public void setName(String name)
        {
            this.name = name;
        }

        public Integer getVersion()
        {
            return version;
        }

        public void setVersion(Integer version)
        {
            this.version = version;
        }
    }

    public static final class Review implements Serializable
    {
        private Integer id;
        private String summary;
        private Integer fkBook;
        private Integer version;
        private Author author;

        public Review()
        {
        }

        public Review(String summary)
        {
            this.summary = summary;
        }

        public Integer getId()
        {
            return id;
        }

        public void setId(Integer id)
        {
            this.id = id;
        }

        public Integer getFkBook()
        {
            return fkBook;
        }

        public void setFkBook(Integer fkBook)
        {
            this.fkBook = fkBook;
        }

        public String getSummary()
        {
            return summary;
        }

        public void setSummary(String summary)
        {
            this.summary = summary;
        }

        public Integer getVersion()
        {
            return version;
        }

        public void setVersion(Integer version)
        {
            this.version = version;
        }

        public Author getAuthor()
        {
            return author;
        }

        public void setAuthor(Author author)
        {
            this.author = author;
        }

        public boolean equals(Object obj)
        {
            boolean result = false;
            if(obj instanceof Review)
            {
                Review other = (Review) obj;
                result = new EqualsBuilder()
                        .append(id, other.id)
                        .append(summary, other.summary)
                        .append(version, other.version)
                        .append(fkBook, other.fkBook)
                        .append(author, other.author)
                        .isEquals();
            }
            return result;
        }
    }

}
TOP

Related Classes of org.apache.ojb.odmg.ObjectImageTest$Book

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.