00001
00029 package org.objectweb.jonas_ejb.container.jorm;
00030
00031 import java.util.ArrayList;
00032 import java.util.HashMap;
00033 import java.util.Map;
00034
00035 import javax.ejb.EJBException;
00036
00037 import org.objectweb.jonas_ejb.container.JContainer;
00038 import org.objectweb.jonas_ejb.container.TraceEjb;
00039 import org.objectweb.jonas_ejb.deployment.api.DeploymentDescEjb2;
00040 import org.objectweb.jonas_ejb.deployment.api.EntityCmp2Desc;
00041 import org.objectweb.jonas_ejb.deployment.api.EntityDesc;
00042 import org.objectweb.jonas_ejb.deployment.api.MethodCmp2Desc;
00043 import org.objectweb.jonas_ejb.lib.EjbqlLimiterRange;
00044 import org.objectweb.jonas_ejb.lib.EjbqlQueryTreeHolder;
00045 import org.objectweb.jonas_lib.deployment.api.DeploymentDescException;
00046 import org.objectweb.jorm.metainfo.api.Manager;
00047 import org.objectweb.medor.api.EvaluationException;
00048 import org.objectweb.medor.api.MedorException;
00049 import org.objectweb.medor.eval.api.ConnectionResources;
00050 import org.objectweb.medor.eval.api.QueryEvaluator;
00051 import org.objectweb.medor.eval.lib.BasicEvaluationMetaData;
00052 import org.objectweb.medor.eval.prefetch.api.PrefetchBuffer;
00053 import org.objectweb.medor.eval.prefetch.lib.PrefetchBufferFactoryImpl;
00054 import org.objectweb.medor.expression.api.ParameterOperand;
00055 import org.objectweb.medor.expression.api.TypingException;
00056 import org.objectweb.medor.lib.Log;
00057 import org.objectweb.medor.optim.api.ExecPlanGenerator;
00058 import org.objectweb.medor.optim.api.QueryTransformer;
00059 import org.objectweb.medor.optim.jorm.Jorm2Rdb;
00060 import org.objectweb.medor.optim.lib.BasicQueryRewriter;
00061 import org.objectweb.medor.optim.lib.FlattenQueryTreeRule;
00062 import org.objectweb.medor.optim.lib.IndexesGenerator;
00063 import org.objectweb.medor.query.api.QueryLeaf;
00064 import org.objectweb.medor.query.api.QueryTree;
00065 import org.objectweb.medor.tuple.api.TupleCollection;
00066 import org.objectweb.util.monolog.api.BasicLevel;
00067
00074 public abstract class MedorFactory extends JormFactory {
00075
00080 protected QueryTransformer queryTransformer = null;
00081
00082 protected Manager miManager = null;
00083
00084 protected ExecPlanGenerator indexesGenerator;
00085
00086 protected boolean optimizeAtInit = false;
00087
00091 private int prefetchIndex;
00092
00096 private EjbqlLimiterRange[] limiterRanges = null;
00097
00098 public MedorFactory() {
00099 super();
00100 if (Log.loggerFactory != TraceEjb.loggerFactory) {
00101 Log.loggerFactory = TraceEjb.loggerFactory;
00102 }
00103 }
00104
00112 public synchronized QueryEvaluator getOptimizedRequest(MethodCmp2Desc methodDesc) throws MedorException {
00113 TraceEjb.logger.log(BasicLevel.DEBUG, "getOptimizedRequest(method name: " + methodDesc.getMethod().getName()
00114 + ")");
00115 try {
00116 EjbqlQueryTreeHolder qth = methodDesc.getQueryTreeHolder(mapper);
00117
00118 setPrefetchIndex(qth.getPrefetchIndex());
00119
00120 if (qth.getQueryOptimizer() == null) {
00121 if (queryTransformer == null) {
00122 ArrayList rules = new ArrayList(2);
00123 rules.add(new FlattenQueryTreeRule());
00124 rules.add(new Jorm2Rdb());
00125 queryTransformer = new BasicQueryRewriter(rules);
00126 }
00127 qth.setQueryOptimizer(new QueryTransformer() {
00128
00129 public QueryTree transform(QueryTree qt) throws MedorException {
00130 QueryTree qt1 = queryTransformer.transform(qt);
00131
00132
00133
00134
00135 if (indexesGenerator == null) {
00136 throw new Error("getOptimizedRequest: indexesGenerator == null");
00137 }
00138 return indexesGenerator.transform(qt1);
00139 }
00140 });
00141 }
00142 limiterRanges = qth.getLimiterRanges();
00143 return qth.getOptimizedQueryTree();
00144 } catch (Exception e) {
00145 throw new MedorException("Impossible to optimize the query " + methodDesc.getQuery(), e);
00146 }
00147 }
00148
00152
00153
00154
00155
00156
00157
00158
00159
00169 public TupleCollection evaluate(Object conn, int methodIndex, ParameterOperand[] parameters) throws MedorException {
00170
00171 MethodCmp2Desc mcd = (MethodCmp2Desc) dd.getMethodDesc(methodIndex);
00172 QueryEvaluator evaluator = getOptimizedRequest(mcd);
00173
00174
00175 ConnectionResources cr = evaluator.getRequiredConnectionResources();
00176
00177
00178 QueryLeaf[] leaves = cr.getRequiredQueryLeafConnection();
00179
00180
00181
00182
00183
00184 if (conn == null) {
00185 throw new MedorException("invalid connection handle [null]");
00186 }
00187 for (int i = 0; (i < leaves.length); i++) {
00188 cr.setConnection(leaves[i], conn);
00189 }
00190
00191 PrefetchBuffer prefetchBuffer = null;
00192 if (mcd.getPrefetch()) {
00193 Object tx = null;
00194 try {
00195 tx = this.getTransactionManager().getTransaction();
00196 if (tx != null) {
00197 prefetchBuffer = mapper.getPrefetchCache().createPrefetchBuffer(new PrefetchBufferFactoryImpl(),
00198 this, tx, getPrefetchIndex());
00199 }
00200 } catch (javax.transaction.SystemException e) {
00201
00202 TraceEjb.logger.log(BasicLevel.ERROR,
00203 "Cannot get the current transaction to create the Prefetch buffer:", e);
00204 }
00205 }
00206
00207 Map evalMDMap = null;
00208 if (limiterRanges.length > 0) {
00209 try {
00210
00211 evalMDMap = new HashMap();
00212 BasicEvaluationMetaData evalMD = new BasicEvaluationMetaData();
00213 EjbqlLimiterRange range = limiterRanges[0];
00214 if (range.getKind() == EjbqlLimiterRange.KIND_PARAMETER) {
00215 evalMD.setLimitedRangeStartAt(parameters[range.getValue()].getInt());
00216 } else {
00217 evalMD.setLimitedRangeStartAt(range.getValue());
00218 }
00219 if (TraceEjb.isDebugQuery()) {
00220 TraceEjb.query.log(BasicLevel.LEVEL_DEBUG, "Query with LIMITer Range Start At = "
00221 + evalMD.getLimitedRangeStartAt() + " for method name " + mcd.getMethod().getName());
00222 }
00223 if (limiterRanges.length > 1) {
00224 range = limiterRanges[1];
00225 if (range.getKind() == EjbqlLimiterRange.KIND_PARAMETER) {
00226 System.out.println("parameters[range.getValue()].getInt() = "
00227 + parameters[range.getValue()].getInt());
00228 evalMD.setLimitedRangeSize(parameters[range.getValue()].getInt());
00229 } else {
00230 evalMD.setLimitedRangeSize(range.getValue());
00231 }
00232 if (TraceEjb.isDebugQuery()) {
00233 TraceEjb.query.log(BasicLevel.LEVEL_DEBUG, "Query with LIMITer Range Size = "
00234 + evalMD.getLimitedRangeSize() + " for method name " + mcd.getMethod().getName());
00235 }
00236 }
00237 evalMDMap.put(leaves[0], evalMD);
00238 } catch (TypingException te) {
00239 throw new MedorException("Invalid parameter for a LIMIT range", te);
00240 }
00241 }
00242 try {
00243 return evaluator.evaluate(parameters, cr, prefetchBuffer, evalMDMap);
00244 } catch (EvaluationException e) {
00245 throw e;
00246 }
00247 }
00248
00249 public void init(EntityDesc ed, JContainer c, String mapperName) {
00250 super.init(ed, c, mapperName);
00251
00252 ecd = (EntityCmp2Desc) ed;
00253
00254
00255 TraceEjb.logger.log(BasicLevel.DEBUG, "Jorm Meta information building");
00256 DeploymentDescEjb2 dd = ecd.getDeploymentDescEjb2();
00257 try {
00258 miManager = dd.getJormManager();
00259 } catch (DeploymentDescException e) {
00260 TraceEjb.logger.log(BasicLevel.ERROR, "impossible to load the jorm meta information into the manager", e);
00261 throw new EJBException("impossible to load the jorm meta information into the manager", e);
00262 }
00263
00264
00265 TraceEjb.logger.log(BasicLevel.DEBUG, "Medor initialisation");
00266 indexesGenerator = new IndexesGenerator();
00267
00268 }
00269
00270 private void setPrefetchIndex(int i) {
00271 prefetchIndex = i;
00272 }
00273
00274 private int getPrefetchIndex() {
00275 return prefetchIndex;
00276 }
00277
00278 }