001    package org.apache.ojb.odmg.collections;
002    
003    /* Copyright 2003-2005 The Apache Software Foundation
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    import java.io.Serializable;
019    
020    import org.apache.commons.lang.builder.ToStringBuilder;
021    import org.apache.ojb.broker.Identity;
022    import org.apache.ojb.broker.OJBRuntimeException;
023    import org.apache.ojb.broker.PBKey;
024    import org.apache.ojb.broker.PersistenceBroker;
025    import org.apache.ojb.broker.PersistenceBrokerAware;
026    import org.apache.ojb.broker.PersistenceBrokerException;
027    import org.apache.ojb.broker.util.logging.Logger;
028    import org.apache.ojb.broker.util.logging.LoggerFactory;
029    import org.apache.ojb.odmg.PBCapsule;
030    import org.apache.ojb.odmg.RuntimeObject;
031    import org.apache.ojb.odmg.TransactionImpl;
032    import org.apache.ojb.odmg.TxManagerFactory;
033    import org.odmg.Transaction;
034    
035    /**
036     * Encapsulates an DList entry object.
037     *
038     * @version $Id: DListEntry.java,v 1.1 2007-08-24 22:17:37 ewestfal Exp $
039     */
040    public class DListEntry implements Serializable, PersistenceBrokerAware
041    {
042        private static final long serialVersionUID = 5251476492626009907L;
043        /*
044         * declare transient, because ManageableCollection entries need to be {@link java.io.Serializable}.
045         */
046        private transient Logger log;
047        protected transient Object realSubject;
048        protected PBKey pbKey;
049    
050        protected Integer id;
051        protected Integer dlistId;
052        protected Identity oid;
053        protected int position;
054    
055        /**
056         * Used to instantiate persistent DLists from DB by the kernel
057         * FOR INTERNAL USE ONLY
058         */
059        public DListEntry()
060        {
061            /*
062            arminw:
063            When PB kernel fill DList with DListEntry, the DListEntry needs to know the current
064            used PBKey, because we need to lookup the real objects when user iterates the list,
065            thus we need the associated PBKey to find right PB/DB connection.
066            TODO: Find a better solution
067            */
068    //        if(getTransaction() == null)
069    //        {
070    //            throw new TransactionNotInProgressException("Materialization of DCollection instances must be done with a tx");
071    //        }
072            getPBKey();
073        }
074    
075        /**
076         * Standard way to instantiate new entries
077         */
078        public DListEntry(DListImpl theDList, Object theObject)
079        {
080            this.dlistId = theDList.getId();
081            this.position = theDList.size();
082            this.realSubject = theObject;
083            this.pbKey = getPBKey();
084        }
085    
086        protected Logger getLog()
087        {
088            if(log == null)
089            {
090                log = LoggerFactory.getLogger(DListEntry.class);
091            }
092            return log;
093        }
094    
095        protected TransactionImpl getTransaction()
096        {
097            return TxManagerFactory.instance().getTransaction();
098        }
099    
100        public PBKey getPBKey()
101        {
102            if(pbKey == null)
103            {
104                TransactionImpl tx = getTransaction();
105                if(tx != null && tx.isOpen())
106                {
107                    pbKey = tx.getBroker().getPBKey();
108                }
109            }
110            return pbKey;
111        }
112    
113        protected void prepareForPersistency(PersistenceBroker broker)
114        {
115            if(oid == null)
116            {
117                if(realSubject == null)
118                {
119                    throw new OJBRuntimeException("Identity and real object are 'null' - Can not persist empty entry");
120                }
121                else
122                {
123                    oid = broker.serviceIdentity().buildIdentity(realSubject);
124                }
125            }
126        }
127    
128        protected void prepareRealSubject(PersistenceBroker broker)
129        {
130            if(oid == null)
131            {
132                throw new OJBRuntimeException("can not return real object, real object and Identity is null");
133            }
134            realSubject = broker.getObjectByIdentity(oid);
135        }
136    
137        public Object getRealSubject()
138        {
139            if(realSubject != null)
140            {
141                return realSubject;
142            }
143            else
144            {
145                TransactionImpl tx = getTransaction();
146                if(tx != null && tx.isOpen())
147                {
148                    prepareRealSubject(tx.getBroker());
149                    if(realSubject != null)
150                    {
151                        RuntimeObject rt = new RuntimeObject(realSubject, tx, false);
152                        tx.lockAndRegister(rt, Transaction.READ, tx.getRegistrationList());
153                    }
154                }
155                else
156                {
157                    PBKey aPbKey = getPBKey();
158                    if(aPbKey != null)
159                    {
160                        PBCapsule capsule = new PBCapsule(aPbKey, null);
161                        try
162                        {
163                            prepareRealSubject(capsule.getBroker());
164                        }
165                        finally
166                        {
167                            capsule.destroy();
168                        }
169                    }
170                    else
171                    {
172                        getLog().warn("No tx, no PBKey - can't materialise object with Identity " + getOid());
173                    }
174                }
175            }
176            return realSubject;
177        }
178    
179        public void setRealSubject(Object realSubject)
180        {
181            this.realSubject = realSubject;
182        }
183    
184        public int getPosition()
185        {
186            return position;
187        }
188    
189        public void setPosition(int newPosition)
190        {
191            position = newPosition;
192        }
193    
194        /**
195         * Gets the dlistId.
196         *
197         * @return Returns a int
198         */
199        public Integer getDlistId()
200        {
201            return dlistId;
202        }
203    
204        /**
205         * Sets the dlistId.
206         *
207         * @param dlistId The dlistId to set
208         */
209        public void setDlistId(Integer dlistId)
210        {
211            this.dlistId = dlistId;
212        }
213    
214        /**
215         * Gets the id.
216         *
217         * @return Returns a int
218         */
219        public Integer getId()
220        {
221            return id;
222        }
223    
224        /**
225         * Sets the id.
226         *
227         * @param id The id to set
228         */
229        public void setId(Integer id)
230        {
231            this.id = id;
232        }
233    
234        public Identity getOid()
235        {
236            return oid;
237        }
238    
239        public void setOid(Identity oid)
240        {
241            this.oid = oid;
242        }
243    
244        /**
245         * return String representation.
246         */
247        public String toString()
248        {
249            ToStringBuilder buf = new ToStringBuilder(this);
250            buf.append("id", id);
251            buf.append("dListId", dlistId);
252            buf.append("position", position);
253            buf.append("identity", oid);
254            buf.append("realSubject", realSubject);
255            return buf.toString();
256        }
257    
258    
259        //===================================================
260        // PersistenceBrokerAware interface methods
261        //===================================================
262        public void beforeInsert(PersistenceBroker broker) throws PersistenceBrokerException
263        {
264            // before insert we have to build the Identity objects of the persistent objects
265            // we can't do this ealier, because we can now expect that the persistent object
266            // was written to DB (we make sure in code that the persistent object was locked before
267            // this entry) and the generated Identity is valid
268            prepareForPersistency(broker);
269        }
270    
271        public void beforeUpdate(PersistenceBroker broker) throws PersistenceBrokerException{}
272        public void beforeDelete(PersistenceBroker broker) throws PersistenceBrokerException{}
273        public void afterLookup(PersistenceBroker broker) throws PersistenceBrokerException{}
274        public void afterDelete(PersistenceBroker broker) throws PersistenceBrokerException{}
275        public void afterInsert(PersistenceBroker broker) throws PersistenceBrokerException{}
276        public void afterUpdate(PersistenceBroker broker) throws PersistenceBrokerException{}
277    }