// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.utils.db;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import com.cloud.utils.Pair;
public class QueryBuilder<S, T> implements MethodInterceptor, SimpleQueryBuilder<S>, SelectQueryBuilder<S, T>, JoinQueryBuilder<S, T> {
public enum Func {
NATIVE("@", 1),
MAX("MAX(@)", 1),
MIN("MIN(@)", 1),
FIRST("FIRST(@)", 1),
LAST("LAST(@)", 1),
SUM("SUM(@)", 1),
COUNT("COUNT(@)", 1),
DISTINCT("DISTINCT(@)", 1);
private String func;
private int count;
Func(String func, int params) {
this.func = func;
this.count = params;
}
@Override
public String toString() {
return func;
}
public int getCount() {
return count;
}
}
protected HashMap<Class<?>, Pair<GenericDaoBase<?,?>, Object>> _entities;
protected ArrayList<Attribute> _specifiedAttrs = new ArrayList<Attribute>();
protected T _resultSetClass;
protected ArrayList<Select<S, T>> _selects;
public QueryBuilder(Class<T> resultSetClass, Class<?>... clazzes) {
_entities = new HashMap<Class<?>, Pair<GenericDaoBase<?,?>, Object>>(clazzes.length);
for (Class<?> clazz : clazzes) {
GenericDaoBase<?,?> dao = GenericDaoBase.getDao(clazz);
Enhancer searchEnhancer = new Enhancer();
searchEnhancer.setSuperclass(clazz);
searchEnhancer.setCallback(this);
Object entity = searchEnhancer.create();
_entities.put(clazz, new Pair<GenericDaoBase<?, ?>, Object>(dao, entity));
}
}
protected void clean() {
_specifiedAttrs = null;
_entities = null;
}
/**
* Constructor for SelectQueryBuilder interface. Must specify the
* table to be performing the query on and the result class to place it in.
* @param entityClass entity class to do the query on.
* @param resultSetClass result class to put the result set in.
*/
public QueryBuilder(Class<S> entityClass, Class<T> resultSetClass) {
_entities = new HashMap<Class<?>, Pair<GenericDaoBase<?,?>, Object>>(1);
GenericDaoBase<?,?> dao = GenericDaoBase.getDao(entityClass);
Enhancer searchEnhancer = new Enhancer();
searchEnhancer.setSuperclass(entityClass);
searchEnhancer.setCallback(this);
Object entity = searchEnhancer.create();
_entities.put(entityClass, new Pair<GenericDaoBase<?, ?>, Object>(dao, entity));
}
@Override
public SimpleQueryBuilder<S> selectFields(Object... fields) {
assert _entities != null && _entities.size() == 1 : "Now you've done it....Stop casting interfaces on the QueryBuilder";
assert _specifiedAttrs.size() > 0 : "You didn't specify any attributes";
if (_selects == null) {
_selects = new ArrayList<Select<S, T>>(fields.length);
}
for (Attribute attr : _specifiedAttrs) {
_selects.add(new Select<S, T>(this, null, attr));
}
_specifiedAttrs.clear();
return this;
}
protected void set(GenericDaoBase<?, ?> dao , String name) {
Attribute attr = dao.getAllAttributes().get(name);
assert (attr != null) : "Searching for a field that's not there: " + name;
_specifiedAttrs.add(attr);
}
@Override
public Object intercept(Object entity, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Class<?> entityClass = entity.getClass().getSuperclass();
Pair<GenericDaoBase<?,?>, Object> daoInfo = _entities.get(entityClass);
assert (daoInfo != null) : "You need to specify " + entityClass + " as one of the entities in the Query";
GenericDaoBase<?,?> dao = daoInfo.first();
String name = method.getName();
if (name.startsWith("get")) {
String fieldName = Character.toLowerCase(name.charAt(3)) + name.substring(4);
set(dao, fieldName);
return null;
} else if (name.startsWith("is")) {
String fieldName = Character.toLowerCase(name.charAt(2)) + name.substring(3);
set(dao, fieldName);
return null;
} else {
assert false : "Perhaps you need to make the method start with get or is?";
}
return proxy.invokeSuper(entity, args);
}
@Override
@SuppressWarnings("unchecked")
public <E> E entity(Class<E> clazz) {
return (E)_entities.get(clazz).second();
}
@Override
@SuppressWarnings("unchecked")
public S entity() {
return (S)_entities.values().iterator().next().second();
}
@Override
public FirstWhere<S, T> where() {
return new Where<S, T>(this);
}
@Override
public SimpleQueryBuilder<S> selectAll() {
return this;
}
public List<Attribute> getSpecifiedAttributes() {
return _specifiedAttrs;
}
public Attribute getSpecifiedAttribute() {
assert _specifiedAttrs.size() == 1 : "You can only specify one attribute";
return _specifiedAttrs.get(0);
}
@Override
public Select<S, T> selectColumn(Object column) {
return null;
}
@Override
public Select<S, T> selectField(Object column) {
// TODO Auto-generated method stub
return null;
}
@Override
public <J> On<S, J, T> innerJoin(Class<J> entityClazz) {
// TODO Auto-generated method stub
return null;
}
}