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 }