db-torque-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Lach, Thierry" <Thierry.L...@bbdodetroit.com>
Subject RE: automatically creating beans from torque objects and vice versa
Date Wed, 16 Mar 2005 20:48:32 GMT

I would definitely favor this.  I've made a couple of attempts to do it myself but didn't
get too far - ran into time priorities and didn't finish.

-----Original Message-----
From: Thomas Fischer [mailto:fischer@seitenbau.net]
Sent: Tuesday, March 15, 2005 1:34 PM
To: torque-dev@db.apache.org
Subject: automatically creating beans from torque objects and vice versa






Hi everyone

It has been suggested several times in the wiki that one should be able to create beans automatically
which correspond to Torque Data objects. This is useful if one wants to transmit objects via
a network and the other side does not know about torque, or if one has a tool like apache
axis which can create xml out of an object, and one does not want to include all Torque related
metadata into the xml.

At the beginning, I tried to let the xxxBaseObject inherit from a xxxBean, and store all persistent
Data in the bean. This did not work because Torque supports inheritance in the object hierarchy,
and this would mean that a object which is a child in a object hierarchy would have to inherit
both from its parent and from its bean, which is not possible in Java So I resorted to a complete
separation between Data Object and beans. There are two public methods in xxxObject, namely
public xxxBean getBean() and public static xxxObject getXxxObject() which are used for Object->Bean
and Bean->Object conversion, respectively (I would rather have used a Constructor for the
latter, but as xxxBaseObject is abstract, this is not an option. Also, a Constructor does
not get inherited by xxxObject)

If complexObjectModel is turned on during generation, the translation also translates all
cached related Objects to beans and vice versa. This is a challenge because of circular references,
e.g.
author.getBooks(0).getAuthor() might either reference back to the original author, or it might
point to another instance of the same Database author object. In order not to lose this information
and create infinite creation loops in the case where the referance points back to the original
object, an identityMap is used to store the mappings which were already translated (the identityMap
is implemented in commons collection and is a map based on the == operator, not on equals()).
If an object is already found in there, it is used, otherwise the translated object is created
and stored in the map. This might sound pretty confusing, below is some example from the BaseBook
and BaseAuthor classes.

Some general points:
There is a switch in the generator whether to generate beans or not. The beans are generated
in a separate subpackage named bean.

Does anyone opposes to adding this functionality to Torque ? Are there any design flaws which
I have not seen yet ? Does someone disagree with some design or implemetation decisions, such
as the aforementioned relationships between Data object and beans, or method names, or anything
I did not think about ?

The stuff is neither in its final stage nor tested. I just wanted to make this known beforehand,
so that anybody wishing to give some input can do so.

  Eagerly awaiting some feedback,

       Thomas

from BaseAuthor.java:
    /**
     * Creates a AuthorBean with the contents of this object
       * This also creates beans for cached related objects, if they exist
       * @return a AuthorBean with the contents of this object
     */
    public AuthorBean getBean()
    {
        return getBean(new IdentityMap());
    }

    /**
     * Creates a AuthorBean with the contents of this object
     * intended for internal use only
     * @param createdBeans a IdentityMap which maps objects
     *        to already created beans
     * @return a AuthorBean with the contents of this object
     */
    AuthorBean getBean(IdentityMap createdBeans)
    {
        AuthorBean result = (AuthorBean) createdBeans.get(this);
        if (result != null ) {
            // we have already created a bean for this object, return it
            return result;
        }
        // no bean exists for this object; create a new one
        result = new AuthorBean();
        createdBeans.put(this, result);

        result.setAuthorId(getAuthorId());
        result.setName(getName());

        if (collBooks != null)
        {
            List relatedBeans = new ArrayList(collBooks.size());
            for (Iterator collBooksIt = collBooks.iterator(); collBooksIt.hasNext(); )
            {
                Book related = (Book) collBooksIt.next();
                BookBean relatedBean = related.getBean(createdBeans);
                relatedBeans.add(relatedBean);
            }
            result.setBookBeans(relatedBeans);
        }

        return result;
    }

    /**
     * Creates an instance of Author with the contents
     * of a AuthorBean.
     * This behaviour could have also been achieved using a constructor,
     * however as this class is abstract no constructors are allowed
     * @param bean the AuthorBean which contents are used to create
     *        the resulting class
     * @return an instance of Author with the contents of bean
     */
    public static Author createAuthor(AuthorBean bean)
        throws TorqueException
    {
        return createAuthor(bean, new IdentityMap());
    }

    /**
     * Creates an instance of Author with the contents
     * of a AuthorBean.
     * This behaviour could have also been achieved using a constructor,
     * however as this class is abstract no constructors are allowed
     * @param bean the AuthorBean which contents are used to create
     *        the resulting class
     * @param createdObjects a IdentityMap which maps beans
     *        to already created objects
     * @return an instance of Author with the contents of bean
     */

    static Author createAuthor(AuthorBean bean, IdentityMap createdObjects)
        throws TorqueException
    {
        Author result = (Author) createdObjects.get(bean);
        if (result != null)
        {
            // we already have an object for the bean, return it
            return result;
        }
        result = new Author();
        createdObjects.put(bean, result);
        {
            List relatedBeans = bean.getBookBeans();
            if (relatedBeans != null)
            {
                for (Iterator relatedBeansIt = relatedBeans.iterator(); relatedBeansIt.hasNext();
)
                {
                    BookBean relatedBean = (BookBean) relatedBeansIt.next();
                    Book related = Book.createBook(relatedBean, createdObjects);
                    result.addBook(related);
                }
            }
        }

        return result;
    }

>From BaseBook.java:

    /**
     * Creates a BookBean with the contents of this object
       * This also creates beans for cached related objects, if they exist
       * @return a BookBean with the contents of this object
     */
    public BookBean getBean()
    {
        return getBean(new IdentityMap());
    }

    /**
     * Creates a BookBean with the contents of this object
     * intended for internal use only
     * @param createdBeans a IdentityMap which maps objects
     *        to already created beans
     * @return a BookBean with the contents of this object
     */
    BookBean getBean(IdentityMap createdBeans)
    {
        BookBean result = (BookBean) createdBeans.get(this);
        if (result != null ) {
            // we have already created a bean for this object, return it
            return result;
        }
        // no bean exists for this object; create a new one
        result = new BookBean();
        createdBeans.put(this, result);

        result.setBookId(getBookId());
        result.setIsbn(getIsbn());
        result.setAuthorId(getAuthorId());
        result.setTitle(getTitle());

        if (aAuthor != null)
        {
            AuthorBean relatedBean = aAuthor.getBean(createdBeans);
            result.setAuthorBean(relatedBean);
        }
        return result;
    }

    /**
     * Creates an instance of Book with the contents
     * of a BookBean.
     * This behaviour could have also been achieved using a constructor,
     * however as this class is abstract no constructors are allowed
     * @param bean the BookBean which contents are used to create
     *        the resulting class
     * @return an instance of Book with the contents of bean
     */
    public static Book createBook(BookBean bean)
        throws TorqueException
    {
        return createBook(bean, new IdentityMap());
    }

    /**
     * Creates an instance of Book with the contents
     * of a BookBean.
     * This behaviour could have also been achieved using a constructor,
     * however as this class is abstract no constructors are allowed
     * @param bean the BookBean which contents are used to create
     *        the resulting class
     * @param createdObjects a IdentityMap which maps beans
     *        to already created objects
     * @return an instance of Book with the contents of bean
     */

    static Book createBook(BookBean bean, IdentityMap createdObjects)
        throws TorqueException
    {
        Book result = (Book) createdObjects.get(bean);
        if (result != null)
        {
            // we already have an object for the bean, return it
            return result;
        }
        result = new Book();
        createdObjects.put(bean, result);

        {
            AuthorBean relatedBean = bean.getAuthorBean();
            if (relatedBean != null)
            {
                Author relatedObject = Author.createAuthor(relatedBean, createdObjects);
                result.setAuthor(relatedObject);
            }
        }
        return result;
    }

from BookBean.java:

public abstract class BaseBookBean
{
    /** The value for the bookId field */
    private int bookId;

    /** The value for the isbn field */
    private String isbn;

    /** The value for the authorId field */
    private int authorId;

    /** The value for the title field */
    private String title;


    /**
     * Get the BookId
     *
     * @return int
     */
    public int getBookId ()
    {
        return bookId;
    }

    /**
     * Set the value of BookId
     *
     * @param v new value
     */
    public void setBookId(int v)
    {
        this.bookId = v;
    }

    /**
     * Get the Isbn
     *
     * @return String
     */
    public String getIsbn ()
    {
        return isbn;
    }

    /**
     * Set the value of Isbn
     *
     * @param v new value
     */
    public void setIsbn(String v)
    {
        this.isbn = v;
    }

    /**
     * Get the AuthorId
     *
     * @return int
     */
    public int getAuthorId ()
    {
        return authorId;
    }

    /**
     * Set the value of AuthorId
     *
     * @param v new value
     */
    public void setAuthorId(int v)
    {
        this.authorId = v;
    }

    /**
     * Get the Title
     *
     * @return String
     */
    public String getTitle ()
    {
        return title;
    }

    /**
     * Set the value of Title
     *
     * @param v new value
     */
    public void setTitle(String v)
    {
        this.title = v;
    }

    private AuthorBean aAuthorBean;

    /**
     * sets an associated AuthorBean object
     *
     * @param v AuthorBean
     */
    public void setAuthorBean(AuthorBean v)
    {
        if (v == null)
        {
             setAuthorId( 0);
        }
        else
        {
            setAuthorId(v.getAuthorId());
        }
        aAuthorBean = v;
    }


    /**
     * Get the associated AuthorBean object
     *
     * @return the associated AuthorBean object
     */
    public AuthorBean getAuthorBean()
    {
        return aAuthorBean;
    }
}

from BaseAuthorBean.java:

public abstract class BaseAuthorBean
{
    /** The value for the authorId field */
    private int authorId;

    /** The value for the name field */
    private String name;

    /**
     * Get the AuthorId
     *
     * @return int
     */
    public int getAuthorId ()
    {
        return authorId;
    }

    /**
     * Set the value of AuthorId
     *
     * @param v new value
     */
    public void setAuthorId(int v)
    {
        this.authorId = v;
    }

    /**
     * Get the Name
     *
     * @return String
     */
    public String getName ()
    {
        return name;
    }

    /**
     * Set the value of Name
     *
     * @param v new value
     */
    public void setName(String v)
    {
        this.name = v;
    }

    /**
     * Collection to store aggregation of collBookBeans
     */
    protected List collBookBeans;

    /**
     * Returns the collection of BookBeans
     */
    public List getBookBeans()
    {
        return collBookBeans;
    }

    /**
     * Sets the collection of BookBeans to the specified value
     */
    public void setBookBeans(List list)
    {
        if (list == null)
        {
            collBookBeans = null;
        }
        else
        {
            collBookBeans = new ArrayList(list);
        }
    }
}


--------------------------------------------------------------------

Dr. Thomas Fischer
Software-Entwicklung
Tel. +49 (0) 7531 36598-22
Fax +49 (0) 7531 36598-11
E-Mail  fischer@seitenbau.com

SEITENBAU GmbH
Robert-Gerwig-Str. 10-12
D-78467 Konstanz
http://www.seitenbau.com

Amtsgericht Konstanz HRB 1528
USt-IdNr.: DE 1905 525 50

Geschäftsführer:
Florian Leinberger | Sebastian Roller | Rainer Henze
Prokuristen:
Jan Bauer | Stefan Eichenhofer


---------------------------------------------------------------------
To unsubscribe, e-mail: torque-dev-unsubscribe@db.apache.org
For additional commands, e-mail: torque-dev-help@db.apache.org


This message and any attachments contain information, which may be confidential or privileged.
 If you are not the intended recipient, please refrain from any disclosure, copying, distribution
or use of this information.  Please be aware that such actions are prohibited.  If you have
received this transmission in error, kindly notify us by calling 1-800-262-4723 or e-mail
to helpdesk@bbdo.com. We appreciate your cooperation.

---------------------------------------------------------------------
To unsubscribe, e-mail: torque-dev-unsubscribe@db.apache.org
For additional commands, e-mail: torque-dev-help@db.apache.org


Mime
View raw message