001    /*
002      Copyright (C) 2001-2003 Laurent Martelli <laurent@aopsys.com>
003    
004      This program is free software; you can redistribute it and/or modify
005      it under the terms of the GNU Lesser General Public License as
006      published by the Free Software Foundation; either version 2 of the
007      License, or (at your option) any later version.
008    
009      This program is distributed in the hope that it will be useful,
010      but WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012      GNU Lesser General Public License for more details.
013    
014      You should have received a copy of the GNU Lesser General Public License
015      along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
017    
018    package org.objectweb.jac.aspects.persistence;
019    
020    import org.apache.log4j.Logger;
021    import org.objectweb.jac.core.AspectComponent;
022    import org.objectweb.jac.core.Interaction;
023    import org.objectweb.jac.core.Wrappee;
024    import org.objectweb.jac.core.Wrapping;
025    import org.objectweb.jac.core.rtti.CollectionItem;
026    import org.objectweb.jac.core.rtti.RttiAC;
027    import org.objectweb.jac.util.ExtArrays;
028    import org.objectweb.jac.util.ExtBoolean;
029    
030    /**
031     * Base class for collection wrappers
032     */
033    
034    public abstract class CollectionWrapper extends AbstractPersistenceWrapper {
035        static Logger logger = Logger.getLogger("persistence");
036    
037        boolean isLoaded = false;
038        CollectionItem collection;
039        Object substance;
040    
041        public CollectionWrapper(AspectComponent ac, 
042                                 Object substance,
043                                 CollectionItem collection, 
044                                 boolean isLoaded) 
045        {
046            super(ac);
047            this.collection = collection;
048            this.substance = substance;
049            this.isLoaded = isLoaded;
050        }
051    
052        boolean cache=false;
053    
054        /**
055         * Load the whole collection if it is not already loaded
056         */
057        public synchronized void load(Wrappee wrappee) throws Exception {
058            if (!isLoaded) {
059                logger.debug("loading collection "+getOID(wrappee)+" - "+wrappee);
060                doLoad(wrappee);
061                isLoaded = true;
062            }
063        }
064    
065        public boolean isLoaded() {
066            return isLoaded;
067        }
068    
069        /**
070         * Unload the collection.
071         */
072        public synchronized void unload(Wrappee wrappee) {
073            logger.debug(getOID(wrappee)+".unload...");
074            isLoaded = false;
075            Wrapping.invokeOrg(wrappee,"clear",ExtArrays.emptyObjectArray);      
076        }
077    
078        /**
079         * Really load the whole collection. This is an abstract method
080         * must be overriden by subclasses.
081         */
082        protected abstract void doLoad(Wrappee wrappee) throws Exception;
083    
084        /**
085         * Remove all instances from the collection
086         */
087        public abstract Object clear(Interaction interaction) throws Exception;
088    
089        public Object preload(Interaction interaction) throws Exception {
090            logger.debug(getOID(interaction.wrappee)+
091                      ".preload for "+interaction.method);
092            try {
093                load(interaction.wrappee);
094            } catch (Exception e) {
095                logger.warn("Failed to preload collection for "+interaction,e);
096            }
097            return proceed(interaction);
098        }
099       
100        public synchronized Object size(Interaction interaction) throws Exception {
101            if (!isLoaded) {
102                long size = getCollectionSize(getOID(interaction.wrappee));
103                // If the collection isEmpty, we can consider it is loaded
104                // even if it not (since it's empty)
105                if (size==0)
106                    isLoaded = true;
107                return new Integer(new Long(size).intValue());
108            } else {
109                return proceed(interaction);
110            }
111        }
112    
113        protected abstract long getCollectionSize(OID oid) throws Exception;
114    
115        public synchronized Object isEmpty(Interaction interaction) throws Exception {
116            if (!isLoaded) {
117                boolean result = getCollectionSize(getOID(interaction.wrappee))==0;
118                // If the collection isEmpty, we can consider it is loaded
119                // even if it not (since it's empty)
120                if (result)
121                    isLoaded = true;
122                return ExtBoolean.valueOf(result);
123            } else {
124                return proceed(interaction);
125            }
126        }
127    
128        // The last time the wrapped object was used
129        long useDate = System.currentTimeMillis();
130    
131        //public Object memorizeUseDate(Interaction i) {
132        //   useDate = System.currentTimeMillis());
133        //   return proceed(i);
134        //}
135    
136        public long getUseDate(Wrappee wrappee) {
137            return useDate;
138        }
139    
140        /**
141         * Sets useDate to current time
142         */
143        protected void touch() {
144            useDate = System.currentTimeMillis();
145        }
146    
147        public abstract Object iterator(Interaction interaction);
148    
149        public boolean isCache() {
150            return cache;
151        }
152    
153        public void setCache(boolean b) {
154            cache = b;
155        }
156    
157        protected Object convert(Object value, Object wrappee) throws Exception {
158            if (value==null) {
159                return null;
160            } else {
161                Class collType = (Class)collection.getComponentType().getDelegate();
162                if (!collType.isAssignableFrom(value.getClass())) {
163                    Object converted = RttiAC.convert(value,collType);
164                    if (converted == value)
165                        logger.warn(
166                            "Failed to convert "+value+" into "+collType.getName()+
167                            " for collection "+substance+"."+collection.getName());
168                    return converted;
169                } else {
170                    return value;
171                }
172            }
173        }
174    }