001    /*
002      Copyright (C) 2002-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    /**
019     * ListWrapper.java
020     *
021     *
022     * Created: Sat Oct 13 16:14:15 2001
023     *
024     * @author <a href="mailto: "Laurent Martelli</a>
025     * @version
026     */
027    
028    package org.objectweb.jac.aspects.persistence;
029    
030    import java.util.Arrays;
031    import java.util.Collection;
032    import java.util.Iterator;
033    import java.util.List;
034    import org.aopalliance.intercept.ConstructorInvocation;
035    import org.aopalliance.intercept.MethodInvocation;
036    import org.apache.log4j.Logger;
037    import org.objectweb.jac.core.AspectComponent;
038    import org.objectweb.jac.core.Interaction;
039    import org.objectweb.jac.core.Wrappee;
040    import org.objectweb.jac.core.Wrapping;
041    import org.objectweb.jac.core.rtti.ClassRepository;
042    import org.objectweb.jac.core.rtti.CollectionItem;
043    import org.objectweb.jac.core.rtti.MethodItem;
044    import org.objectweb.jac.util.ExtBoolean;
045    
046    /**
047     * A wrapper for the list interface.
048     */
049    public class ListWrapper extends CollectionWrapper {
050        static Logger logger = Logger.getLogger("persistence");
051    
052        public ListWrapper(AspectComponent ac,
053                           Object substance,
054                           CollectionItem collection, 
055                           boolean isLoaded) 
056        {
057            super(ac, substance, collection, isLoaded);
058        }
059    
060        protected void doLoad(Wrappee wrappee) throws Exception {
061            OID oid = getOID(wrappee);
062            List list = oid.getStorage().getList(oid);
063            MethodItem add = cr.getClass(wrappee).getMethod("add(java.lang.Object)");
064            Object[] params = new Object[1];
065            for (int i=0; i<list.size(); i++) {
066                try {
067                    //list.set(i, normalizeOutput(list.get(i)));
068                    params[0] = convert(normalizeOutput(list.get(i)),wrappee);
069                    Wrapping.invokeOrg(wrappee, add, params);
070                } catch (NoSuchOIDError e) {
071                    logger.error(
072                        "ListWrapper.doLoad("
073                        + oid + "): "+collection.getName()+
074                        ": skipping item "+i+" with unknown OID " + list.get(i));
075                    list.set(i, null);
076                } catch (Exception e) {
077                    logger.error(
078                        "ListWrapper.doLoad("
079                        + oid + "): "+collection.getName()+
080                        ": skipping item "+i+" because of exception",e);
081                    list.set(i, null);
082                }
083            }
084            /*
085            attrdef(ATTR_ADDED, "true");
086            // Keep the number of dynamic invocations to the minimum
087            Wrapping.invokeOrg(wrappee, "addAll", new Object[] { list });
088            attrdef(ATTR_ADDED, null);
089            */
090        }
091    
092        public Object contains(Interaction interaction) throws Exception {
093            if (isLoaded) {
094                return interaction.proceed();
095            } else {
096                OID oid = getOID(interaction.wrappee);
097                return ExtBoolean.valueOf(
098                    oid.getStorage().listContains(
099                        oid,
100                        normalizeInput(interaction.args[0])));
101            }
102        }
103    
104        public Object add(Interaction interaction) throws Exception {
105            logger.debug("adding " + interaction.args[0]
106                    + " to list " + getOID(interaction.wrappee));
107            Object result = Boolean.TRUE;
108            if (isLoaded)
109                result = interaction.proceed();
110    
111            OID oid = getOID(interaction.wrappee);
112            if (interaction.args.length == 1) {
113                // add(Object o)
114                oid.getStorage().addToList(
115                    oid,
116                    normalizeInput(interaction.args[0]));
117            } else if (interaction.args.length == 2) {
118                // add(int index, Object o)
119                oid.getStorage().addToList(
120                    oid,
121                    ((Integer) interaction.args[0]).longValue(),
122                    normalizeInput(interaction.args[1]));
123            }
124            return result;
125        }
126    
127        public Object addAll(Interaction interaction) throws Exception {
128            logger.debug("adding " + interaction.args[0]
129                    + " to list " + getOID(interaction.wrappee));
130            Object result = Boolean.TRUE;
131            if (isLoaded)
132                result = interaction.proceed();
133            if (interaction.args.length==1) {
134                // addAll(Collection c)
135                Iterator i = ((Collection)interaction.args[0]).iterator();
136                OID cid = getOID(interaction.wrappee);
137                Storage storage = cid.getStorage();
138                while (i.hasNext()) {
139                    storage.addToList(
140                        cid, normalizeInput(i.next()));
141                }
142            } else {
143                // addAll(int index, Collection c)
144                Iterator i = ((Collection)interaction.args[0]).iterator();
145                OID cid = getOID(interaction.wrappee);
146                long index = ((Integer) interaction.args[0]).longValue();
147                Storage storage = cid.getStorage();
148                while (i.hasNext()) {
149                    storage.addToList(
150                        cid, index++, normalizeInput(i.next()));
151                }
152            }
153            return result;
154        }
155    
156        public Object get(Interaction interaction) throws Exception {
157            touch();
158            if (isLoaded) {
159                return interaction.proceed();
160            } else {
161                OID oid = getOID(interaction.wrappee);
162                return normalizeOutput(
163                    oid.getStorage().getListItem(
164                        oid,
165                        ((Integer) interaction.args[0]).longValue()));
166            }
167        }
168    
169        public Object remove(Interaction interaction) throws Exception {
170            touch();
171            logger.debug("remove : "+ interaction.wrappee
172                         + "," + Arrays.asList(interaction.args));
173            Object result = null;
174            if (isLoaded) {
175                result = interaction.proceed();
176            } else {
177                // WRONG!!!
178                result = Boolean.TRUE;
179            }
180            logger.debug("proceeded");
181            OID oid = getOID(interaction.wrappee);
182            if (interaction.args[0] instanceof Integer) {
183                logger.debug("remove position");
184                oid.getStorage().removeFromList(
185                    oid,
186                    ((Integer) interaction.args[0]).longValue());
187            } else {
188                logger.debug("remove value");
189                oid.getStorage().removeFromList(
190                    oid,
191                    normalizeInput(interaction.args[0]));
192            }
193            logger.debug("value removed");
194            return result;
195        }
196    
197        public Object removeRange(Interaction interaction) throws Exception {
198            // removeRange(int fromIndex, int toIndex)
199            touch();
200            if (isLoaded) {
201                interaction.proceed();
202            }
203            int from = ((Integer)interaction.args[0]).intValue();
204            int to = ((Integer)interaction.args[1]).intValue();
205            int size = ((Integer)size(interaction)).intValue();
206            if (to>size)
207                to = size;
208            OID cid = getOID(interaction.wrappee);
209            Storage storage = cid.getStorage();
210            for (; from<to; from++) {
211                storage.removeFromList(cid,from);
212            }
213            return null;
214        }
215    
216        /**
217         * Remove all instances from the collection
218         */
219        public Object clear(Interaction interaction) throws Exception {
220            touch();
221            logger.debug("clear");
222            Object result = interaction.proceed();
223            OID oid = getOID(interaction.wrappee);
224            oid.getStorage().clearList(oid);
225            return result;
226        }
227    
228        public Object set(Interaction interaction) throws Exception {
229            touch();
230            if (isLoaded())
231                interaction.proceed();
232            OID oid = getOID(interaction.wrappee);
233            oid.getStorage().setListItem(
234                oid,
235                ((Integer) interaction.args[0]).intValue(),
236                interaction.args[1]);
237            return null;
238        }
239    
240        public Object indexOf(Interaction interaction) throws Exception {
241            touch();
242            if (isLoaded) {
243                return interaction.proceed();
244            } else {
245                OID oid = getOID(interaction.wrappee);
246                return new Integer(
247                    new Long(
248                        oid.getStorage().getIndexInList(
249                            oid,
250                            normalizeInput(interaction.args[0])))
251                        .intValue());
252            }
253        }
254    
255        public Object lastIndexOf(Interaction interaction) throws Exception {
256            touch();
257            if (isLoaded) {
258                return interaction.proceed();
259            } else {
260                OID oid = getOID(interaction.wrappee);
261                return new Integer(
262                    new Long(
263                        oid.getStorage().getLastIndexInList(
264                            oid,
265                            normalizeInput(interaction.args[0])))
266                        .intValue());
267            }
268        }
269    
270        protected long getCollectionSize(OID oid) throws Exception {
271            return oid.getStorage().getListSize(oid);
272        }
273    
274        public Object iterator(Interaction interaction) {
275            touch();
276            return new ListIterator(interaction.wrappee);
277        }
278    
279        public Object invoke(MethodInvocation invocation) throws Throwable {
280            String name = invocation.getMethod().getName();
281            Interaction interaction = (Interaction) invocation;
282            if (name.equals("iterator")) {
283                load(interaction.wrappee);
284                //return iterator(interaction);
285                return interaction.proceed();
286            } else if (name.equals("isEmpty")) {
287                return isEmpty(interaction);
288            } else if (name.equals("size")) {
289                return size(interaction);
290            } else if (name.equals("get")) {
291                return get(interaction);
292            } else if (name.equals("indexOf")) {
293                return indexOf(interaction);
294            } else if (name.equals("lastIndexOf")) {
295                return lastIndexOf(interaction);
296            } else if (name.equals("clear")) {
297                return clear(interaction);
298            } else if (name.equals("set")) {
299                return set(interaction);
300            } else if (name.equals("add")) {
301                return add(interaction);
302            } else if (name.equals("addAll")) {
303                return addAll(interaction);
304            } else if (name.equals("remove")) {
305                return remove(interaction);
306            } else if (name.equals("contains")) {
307                return contains(interaction);
308            } else if (name.equals("toArray")) {
309                load(interaction.wrappee);
310                return interaction.proceed();
311            } else if (name.equals("clone")) {
312                load(interaction.wrappee);
313                return interaction.proceed();
314            } else if (name.equals("removeRange")) {
315                return removeRange(interaction);
316            } else {
317                logger.error("ListWrapper: don't know what to do with method "+name);
318            }
319            return interaction.proceed();
320        }
321    
322    }