/**
* Copyright (C) 2001-2005 France Telecom
* Contact: alexandre.lefebvre@rd.francetelecom.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package org.objectweb.speedo.query.lib;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import org.objectweb.jorm.metainfo.api.Class;
import org.objectweb.jorm.metainfo.api.Manager;
import org.objectweb.jorm.util.api.Loggable;
import org.objectweb.medor.api.Field;
import org.objectweb.medor.api.MedorException;
import org.objectweb.medor.query.api.QueryTree;
import org.objectweb.medor.query.api.QueryTreeField;
import org.objectweb.medor.query.jorm.lib.ClassExtent;
import org.objectweb.medor.query.jorm.lib.PNameField;
import org.objectweb.medor.query.jorm.lib.QueryBuilder;
import org.objectweb.speedo.api.SpeedoException;
import org.objectweb.speedo.query.jdo.parser.SpeedoQLAbstractVisitor;
import org.objectweb.util.monolog.api.Logger;
import org.objectweb.util.monolog.api.LoggerFactory;
/**
*
*
* @author Alexandre Lefebvre
*/
public class SpeedoQueryHelper implements Loggable {
/** Logger for monolog.
*/
public Logger logger = null;
public boolean debug = false;
/**
* the name of the current class
*/
protected String curClass = null;
protected Manager jmiManager;
protected boolean includeSubClasses;
/**
* ids is a temporary structure to store variables, parameters, name
* definitions, and build corresponding QueryTree(s)
* key: the name to resolve
* value: an IdValue object which contains the name, the paths, and the
* corresponding QueryTree (see the definition of IdValue object in
* SpeedoQLAbstractVisitor object)
*/
protected Map ids = new HashMap();
/**
* Values associated with each declared identifiers
*/
protected class IdValue {
// Paths used in the select and where clauses starting with the
// corresponding id
private ArrayList paths = null;
// abstract schema name or collection values path
public String[] name = null;
// The query tree which corresponds to the id and the paths
public QueryTree qt = null;
// one of 4 possibilities
public int nameType = SpeedoQLAbstractVisitor.UNDEFINED;
public String alias;
public IdValue(String[] name, int nameType) {
this();
this.name = name;
this.nameType = nameType;
}
public IdValue(String pathName, int nameType) {
this(pathName);
this.nameType = nameType;
}
public IdValue(String pathName) {
this();
name = splitPath(pathName);
}
public IdValue() {
paths = new ArrayList();
}
public void addPath(String path) {
if (!paths.contains(path)) {
paths.add(path);
}
}
public String[] getSplitedPath(int idx) {
return splitPath((String) paths.get(idx));
}
public String getMergedPath(int idx) {
return (String) paths.get(idx);
}
public int getDeclaredPathLength() {
return paths.size();
}
/**
* this method returns the internal representation of an IdValue.
* this method is not optimized, because we don't need to call it
* a lot of times.
*/
public String toString() {
String resName = new String();
if (name != null) {
for (int i = 0; i < name.length; i++)
resName += name[i] + ".";
resName = "[name=" + resName.substring(0, resName.length() - 1) + "]";
} else
resName = "[name=null] ";
String resPath = new String();
for (int i = 0; i < paths.size(); i++)
resPath += (String) paths.get(i) + " & ";
return resName + " - [path=" + resPath + "] - [QT=" + ((qt == null) ? "null" : "something :-)") + "]";
}
}
/**
* split a dot separated path into tokens
*/
protected String[] splitPath(String path) {
StringTokenizer st = new StringTokenizer(path, ".");
String[] ret = new String[st.countTokens()];
for (int i = 0; i < ret.length; i++) {
ret[i] = st.nextToken();
}
return ret;
}
protected QueryTreeField define(QueryBuilder theqb, String id, String alias) throws MedorException, SpeedoException {
String[] path = splitPath(id);
if (!theqb.contains(path[0])) {
IdValue idv = (IdValue) ids.get(path[0]);
String[] name = idv.name;
PNameField pnf;
if (name.length == 1) {
pnf = extent(name[0], path[0]);
theqb.define(path[0], pnf);
} else {
pnf = (PNameField) define(theqb, mergePath(name), alias);
if (!path[0].equals(alias)) {
theqb.define(path[0], pnf);
}
}
}
return theqb.navigate(path,alias);
}
protected PNameField extent(String classname, String alias) throws SpeedoException, MedorException {
if (classname == null) {
throw new NullPointerException("class name not defined");
}
Class theClass = jmiManager.getClass(classname);
if (theClass == null) {
throw new SpeedoException
("Class '" + classname +
"' has not been declared in the jorm meta information");
}
ClassExtent ext = new ClassExtent(theClass, alias, Field.PNAMENAME, false);
if (classname.equals(this.curClass)) {
ext.setWithSubClasses(includeSubClasses);
}
return (PNameField) ext.getField(ext.getPNameFieldName());
}
protected String mergePath(String[] path, int begin, int length) {
if (length == 0)
return "";
StringBuffer ret = new StringBuffer();
for (int i = begin; i < (begin + length); i++) {
ret.append(path[i]);
ret.append('.');
}
ret.deleteCharAt(ret.length() - 1);
return ret.toString();
}
/**
* @param path the input path
* @return the merge tokens into a dot separated path
*/
protected String mergePath(String[] path) {
return (mergePath(path, 0, path.length));
}
// IMPLEMENTATION OF THE Loggable INTERFACE //
//------------------------------------------//
public void setLogger(Logger logger) {
this.logger = logger;
}
public Logger getLogger() {
return logger;
}
public void setLoggerFactory(LoggerFactory loggerFactory) {
}
public LoggerFactory getLoggerFactory() {
return null;
}
}