001    package org.apache.ojb.odmg.collections;
002    
003    /* Copyright 2002-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    import java.util.Map.Entry;
020    
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.TransactionExt;
031    import org.apache.ojb.odmg.TransactionImpl;
032    import org.apache.ojb.odmg.TxManagerFactory;
033    
034    /**
035     * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
036     * @version $Id: DMapEntry.java,v 1.1 2007-08-24 22:17:37 ewestfal Exp $
037     */
038    
039    public class DMapEntry implements Entry, Serializable, PersistenceBrokerAware
040    {
041        private static final long serialVersionUID = 4382757889982004339L;
042        private transient Logger log = LoggerFactory.getLogger(DMapEntry.class);
043    
044        private PBKey pbKey;
045    
046        private Integer id;
047        private Integer dmapId;
048        private Identity keyOid;
049        private Identity valueOid;
050    
051        /* declare transient because the object is not required to be serializable and we can reload it via the oid */
052        private transient Object keyRealSubject;
053        /* declare transient because the object is not required to be serializable and we can reload it via the oid */
054        private transient Object valueRealSubject;
055    
056        /**
057         * Used to materialize DMaps from the database.
058         */
059        public DMapEntry()
060        {
061    //        if(getTransaction() == null)
062    //        {
063    //            throw new TransactionNotInProgressException("Materialization of DCollection instances must be done with a tx");
064    //        }
065            this.pbKey = getPBKey();
066        }
067    
068        /**
069         * DMapEntry constructor comment.
070         */
071        public DMapEntry(DMapImpl map, Object key, Object value)
072        {
073            if(map != null)
074            {
075                dmapId = map.getId();
076            }
077            keyRealSubject = key;
078            valueRealSubject = value;
079            getPBKey();
080        }
081    
082        protected Logger getLog()
083        {
084            if(log == null)
085            {
086                log = LoggerFactory.getLogger(DMapEntry.class);
087            }
088            return log;
089        }
090    
091        protected TransactionImpl getTransaction()
092        {
093            return TxManagerFactory.instance().getTransaction();
094        }
095    
096        public PBKey getPBKey()
097        {
098            if(pbKey == null)
099            {
100                TransactionImpl tx = getTransaction();
101                if(tx != null && tx.isOpen())
102                {
103                    pbKey = tx.getBroker().getPBKey();
104                }
105            }
106            return pbKey;
107        }
108    
109        protected void prepareForPersistency(PersistenceBroker broker)
110        {
111            if(keyOid == null)
112            {
113                if(keyRealSubject == null)
114                {
115                    throw new OJBRuntimeException("Key identity and real key object are 'null' - Can not persist empty entry");
116                }
117                else
118                {
119                    keyOid = broker.serviceIdentity().buildIdentity(keyRealSubject);
120                }
121            }
122            if(valueOid == null)
123            {
124                if(valueRealSubject == null)
125                {
126                    throw new OJBRuntimeException("Key identity and real key object are 'null' - Can not persist empty entry");
127                }
128                else
129                {
130                    valueOid = broker.serviceIdentity().buildIdentity(valueRealSubject);
131                }
132            }
133        }
134    
135        protected void prepareKeyRealSubject(PersistenceBroker broker)
136        {
137            if(keyOid == null)
138            {
139                getLog().info("Cannot retrieve real key object because its id is not known");
140            }
141            else
142            {
143                keyRealSubject = broker.getObjectByIdentity(keyOid);
144            }
145        }
146    
147        protected void prepareValueRealSubject(PersistenceBroker broker)
148        {
149            if(valueOid == null)
150            {
151                getLog().info("Cannot retrieve real key object because its id is not known");
152            }
153            else
154            {
155                valueRealSubject = broker.getObjectByIdentity(valueOid);
156            }
157        }
158    
159        /**
160         * Returns the real key object.
161         */
162        public Object getRealKey()
163        {
164            if(keyRealSubject != null)
165            {
166                return keyRealSubject;
167            }
168            else
169            {
170                TransactionExt tx = getTransaction();
171    
172                if((tx != null) && tx.isOpen())
173                {
174                    prepareKeyRealSubject(tx.getBroker());
175                }
176                else
177                {
178                    if(getPBKey() != null)
179                    {
180                        PBCapsule capsule = new PBCapsule(getPBKey(), null);
181    
182                        try
183                        {
184                            prepareKeyRealSubject(capsule.getBroker());
185                        }
186                        finally
187                        {
188                            capsule.destroy();
189                        }
190                    }
191                    else
192                    {
193                        getLog().warn("No tx, no PBKey - can't materialise key with Identity " + getKeyOid());
194                    }
195                }
196            }
197            return keyRealSubject;
198        }
199    
200        /* (non-Javadoc)
201         * @see java.util.Map.Entry#getKey()
202         */
203        public Object getKey()
204        {
205            // we don't save the key object itself but only its identiy
206            // so we now might have to load the object from the db
207            if((keyRealSubject == null))
208            {
209                return getRealKey();
210            }
211            else
212            {
213                return keyRealSubject;
214            }
215        }
216    
217        /**
218         * Returns the real value object.
219         */
220        public Object getRealValue()
221        {
222            if(valueRealSubject != null)
223            {
224                return valueRealSubject;
225            }
226            else
227            {
228                TransactionExt tx = getTransaction();
229    
230                if((tx != null) && tx.isOpen())
231                {
232                    prepareValueRealSubject(tx.getBroker());
233                }
234                else
235                {
236                    if(getPBKey() != null)
237                    {
238                        PBCapsule capsule = new PBCapsule(getPBKey(), null);
239    
240                        try
241                        {
242                            prepareValueRealSubject(capsule.getBroker());
243                        }
244                        finally
245                        {
246                            capsule.destroy();
247                        }
248                    }
249                    else
250                    {
251                        getLog().warn("No tx, no PBKey - can't materialise value with Identity " + getKeyOid());
252                    }
253                }
254            }
255            return valueRealSubject;
256        }
257    
258        /* (non-Javadoc)
259         * @see java.util.Map.Entry#getValue()
260         */
261        public Object getValue()
262        {
263            // we don't save the value object itself but only its identiy
264            // so we now might have to load the object from the db
265            if((valueRealSubject == null))
266            {
267                return getRealValue();
268            }
269            else
270            {
271                return valueRealSubject;
272            }
273        }
274    
275        /*
276         * (non-Javadoc)
277         * @see java.util.Map.Entry#setValue(java.lang.Object)
278         */
279        public Object setValue(Object obj)
280        {
281            Object old = valueRealSubject;
282    
283            valueRealSubject = obj;
284            return old;
285        }
286    
287        /**
288         * Gets the dmapId.
289         *
290         * @return Returns a int
291         */
292        public Integer getDmapId()
293        {
294            return dmapId;
295        }
296    
297        /**
298         * Sets the dmapId.
299         *
300         * @param dmapId The dmapId to set
301         */
302        public void setDmapId(Integer dmapId)
303        {
304            this.dmapId = dmapId;
305        }
306    
307        /**
308         * Gets the id.
309         *
310         * @return Returns a int
311         */
312        public Integer getId()
313        {
314            return id;
315        }
316    
317        /**
318         * Sets the id.
319         *
320         * @param id The id to set
321         */
322        public void setId(Integer id)
323        {
324            this.id = id;
325        }
326    
327        public Identity getKeyOid()
328        {
329            return keyOid;
330        }
331    
332        public void setKeyOid(Identity keyOid)
333        {
334            this.keyOid = keyOid;
335        }
336    
337        public Identity getValueOid()
338        {
339            return valueOid;
340        }
341    
342        public void setValueOid(Identity valueOid)
343        {
344            this.valueOid = valueOid;
345        }
346    
347        //===================================================
348        // PersistenceBrokerAware interface methods
349        //===================================================
350        public void beforeInsert(PersistenceBroker broker) throws PersistenceBrokerException
351        {
352            // before insert we have to build the Identity objects of the persistent objects
353            // we can't do this ealier, because we can now expect that the persistent object
354            // was written to DB (we make sure in code that the persistent object was locked before
355            // this entry) and the generated Identity is valid
356            prepareForPersistency(broker);
357        }
358    
359        public void beforeUpdate(PersistenceBroker broker) throws PersistenceBrokerException{}
360        public void beforeDelete(PersistenceBroker broker) throws PersistenceBrokerException{}
361        public void afterLookup(PersistenceBroker broker) throws PersistenceBrokerException{}
362        public void afterDelete(PersistenceBroker broker) throws PersistenceBrokerException{}
363        public void afterInsert(PersistenceBroker broker) throws PersistenceBrokerException{}
364        public void afterUpdate(PersistenceBroker broker) throws PersistenceBrokerException{}
365    }