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:[EMAIL PROTECTED]
Sent: Tuesday, March 15, 2005 1:34 PM
To: [email protected]
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  [EMAIL PROTECTED]

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: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


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 [EMAIL 
PROTECTED] We appreciate your cooperation.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to