Re: Temporary Objects

From: Mike Kienenberger (mkienen..mail.com)
Date: Tue Apr 10 2007 - 15:44:25 EDT

  • Next message: Jens Mayer: "Testing the connection"

    On 4/10/07, Peter Karich <peatha..ahoo.de> wrote:
    > Do you mean that "nonpersistent -> (non)persistent" will be complicated?
    > Why? I can do the following:
    >
    > public void addToManyTarget(Object obj, ...)
    > { if(this.isNonpersistent()) {
    > allObjects.add(obj);
    >
    > } else {
    > if obj.isNonpersistent() {
    > nonpersistentSet.add(obj);
    >
    > } else {
    > super.addToManyTarget(obj, ....);
    > }
    > }
    > }
    >
    > Would this work?

    I'm not really following what you're trying to do here. My
    assumption was that your persistent and non-persistent objects were
    instances of the same class. So any time you add an object as the
    target of another object, you'd need to set the reverse relationship
    if you want that to exist. Here's how I did it in my
    cayenne-api-compatible non-persistent framework. Note that every
    DataObject inherits from this BaseEntityStub superclass (instead of
    CayenneDataObject). I also throw an exception if there's an attempt
    to assign non-BaseEntityStub objects as relationship targets of
    BaseEntityStub objects (and vise versa). I use the Cayenne template
    generator to define and initialize populateRelationshipMapsFromArrays
    for each Entity class, which is used to figure out the reverse
    relationships for a given relationship. Again, this code duplicates
    the Cayenne functionality for non-persistent objects. It does not mix
    the two, but could probably be modified with what I sent you before in
    order to do so.

        private void checkObjectType(BaseEntity val)
        {
            if (null == val)
            {
                return;
            }

                if (false == val instanceof BaseEntityStub)
                {
                        throw new RuntimeException("BaseEntity class " +
    val.getClass().getName() + " is not of type BaseEntityStub");
                }
        }

            public void setToOneTarget(String relName, BaseEntity val, boolean setReverse)
        {
            BaseEntity oldVal = (BaseEntity)map.get(relName);
            // skip initial assignment if nothing changed
            if (setReverse && safeEquals(oldVal, val))
            {
                return;
            }

            checkObjectType(val);

            if (setReverse)
            {
                if (null != oldVal)
                {
                    unsetReverseRelationship(relName, oldVal);
                }
                if (null != val)
                {
                    setReverseRelationship(relName, val);
                }
            }

            map.put(relName, val);
        }
            
        public void addToManyTarget(String relName, BaseEntity val,
    boolean setReverse)
        {
            checkObjectType(val);

            if (setReverse)
            {
                setReverseRelationship(relName, val);
            }

            List targetList = (List)map.get(relName);
            if (null == targetList)
            {
                targetList = new ArrayList();
                map.put(relName, targetList);
            }

            if (targetList.contains(val))
            {
                throw new RuntimeException("val " + val + " " +
    val.getPrimaryKey() + " is already in " + relName);
            }
            targetList.add(val);
        }

        public void removeToManyTarget(String relName, BaseEntity val,
    boolean setReverse)
        {
            checkObjectType(val);

            if (setReverse)
            {
                unsetReverseRelationship(relName, val);
            }

            List targetList = (List)map.get(relName);
            if (null == targetList)
            {
                throw new RuntimeException("Unsupported operation");
            }

            targetList.remove(val);
        }

        abstract protected void populateRelationshipMapsFromArrays();

        private void setReverseRelationship(String relName, BaseEntity val) {
            if (null == val)
            {
                throw new NullPointerException("val is null");
            }

            if (null == reverseRelationshipsForForwardRelationships)
            {
                populateRelationshipMapsFromArrays();
            }
            String reverseName =
    (String)reverseRelationshipsForForwardRelationships.get(relName);
                if (null != reverseName)
            {
                Boolean reverseToMany =
    (Boolean)reverseRelationshipTypeForForwardRelationships.get(relName);
                if (null != reverseToMany)
                {
                    if (reverseToMany.booleanValue())
                    {
                        ((BaseEntityStub)val).addToManyTarget(reverseName,
    this, false);
                    }
                    else
                    {
                        ((BaseEntityStub)val).setToOneTarget(reverseName,
    this, false);
                    }
                }
            }
            }

        private void unsetReverseRelationship(String relName, BaseEntity val) {
            if (null == val)
            {
                throw new NullPointerException("val is null");
            }

            if (null == reverseRelationshipsForForwardRelationships)
            {
                populateRelationshipMapsFromArrays();
            }
            String reverseName =
    (String)reverseRelationshipsForForwardRelationships.get(relName);
            if (null != reverseName)
            {
                Boolean reverseToMany =
    (Boolean)reverseRelationshipTypeForForwardRelationships.get(relName);
                if (null != reverseToMany)
                {
                    if (reverseToMany.booleanValue())
                    {

    ((BaseEntityStub)val).removeToManyTarget(reverseName, this, false);
                    }
                    else
                    {
                        ((BaseEntityStub)val).setToOneTarget(reverseName,
    null, false);
                    }
                }
            }
            }

    > > And that's not going to handle what happens if you try to do a query
    > > on object sets that are both persistent and non-persistent.
    >
    > I will not get the references in the nonpersistent-object-list, right?

    Cayenne queries will only go against the database/persistent objects.

    > Another question: How does cayenne hold objects in memory?
    > As a normal reference, as WeakReference or even as PhantomReference?

    I have no idea :-) I leave that kind of stuff to the experts :-)



    This archive was generated by hypermail 2.0.0 : Tue Apr 10 2007 - 15:44:58 EDT