// 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.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.persistence.Transient;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import com.cloud.utils.db.GenericSearchBuilder.Condition;
import com.cloud.utils.db.GenericSearchBuilder.Select;
import com.cloud.utils.db.SearchCriteria.Func;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria.SelectType;
public class SearchCriteria2<T, K> implements SearchCriteriaService<T, K>, MethodInterceptor{
GenericDao<? extends Serializable, ? extends Serializable> _dao;
final protected Map<String, Attribute> _attrs;
protected ArrayList<Attribute> _specifiedAttrs;
protected T _entity;
protected ArrayList<GenericSearchBuilder.Condition> _conditions;
protected ArrayList<Select> _selects;
private final HashMap<String, Object[]> _params = new HashMap<String, Object[]>();
protected Class<K> _resultType;
protected SelectType _selectType;
protected Class<T> _entityBeanType;
protected SearchCriteria2(T entity, Class<K> resultType, final Map<String, Attribute> attrs, GenericDao<? extends Serializable, ? extends Serializable> dao) {
_entityBeanType = (Class<T>)entity.getClass();
_dao = dao;
_resultType = resultType;
_attrs = attrs;
_entity = entity;
_conditions = new ArrayList<Condition>();
_specifiedAttrs = new ArrayList<Attribute>();
}
static public <T, K> SearchCriteria2<T, K> create(Class<T> entityType, Class<K> resultType) {
GenericDao<? extends Serializable, ? extends Serializable> dao = (GenericDao<? extends Serializable, ? extends Serializable>)GenericDaoBase.getDao(entityType);
assert dao != null : "Can not find DAO for " + entityType.getName();
SearchCriteria2<T, K> sc = dao.createSearchCriteria2(resultType);
return sc;
}
static public <T, K> SearchCriteria2<T, K> create(Class<T> entityType) {
GenericDao<? extends Serializable, ? extends Serializable> dao = (GenericDao<? extends Serializable, ? extends Serializable>)GenericDaoBase.getDao(entityType);
assert dao != null : "Can not find DAO for " + entityType.getName();
SearchCriteria2<T, K> sc = dao.createSearchCriteria2();
return sc;
}
@Override
public void selectField(Object... useless) {
assert _entity != null : "SearchBuilder cannot be modified once it has been setup";
assert _specifiedAttrs.size() > 0 : "You didn't specify any attributes";
if (_selects == null) {
_selects = new ArrayList<Select>();
}
for (Attribute attr : _specifiedAttrs) {
Field field = null;
try {
field = _resultType.getDeclaredField(attr.field.getName());
field.setAccessible(true);
} catch (SecurityException e) {
} catch (NoSuchFieldException e) {
}
_selects.add(new Select(Func.NATIVE, attr, field, null));
}
_specifiedAttrs.clear();
}
private void constructCondition(String conditionName, String cond, Attribute attr, Op op) {
assert _entity != null : "SearchBuilder cannot be modified once it has been setup";
assert op == null || _specifiedAttrs.size() == 1 : "You didn't select the attribute.";
assert op != Op.SC : "Call join";
GenericSearchBuilder.Condition condition = new GenericSearchBuilder.Condition(conditionName, cond, attr, op);
_conditions.add(condition);
_specifiedAttrs.clear();
}
private void setParameters(String conditionName, Object... params) {
assert _conditions.contains(new Condition(conditionName)) : "Couldn't find " + conditionName;
_params.put(conditionName, params);
}
@Override
public void addAnd(Object useless, Op op, Object...values) {
String uuid = UUID.randomUUID().toString();
constructCondition(uuid, " AND ", _specifiedAttrs.get(0), op);
setParameters(uuid, values);
}
@Override
public List<K> list() {
done();
SearchCriteria sc1 = createSearchCriteria();
if (isSelectAll()) {
return (List<K>)_dao.search(sc1, null);
} else {
return (List<K>)_dao.customSearch(sc1, null);
}
}
private boolean isSelectAll() {
return _selects == null || _selects.size() == 0;
}
@Override
public T getEntity() {
return (T) _entity;
}
private SearchCriteria<K> createSearchCriteria() {
return new SearchCriteria<K>(_attrs, _conditions, _selects, _selectType, _resultType, _params);
}
private void set(String name) {
Attribute attr = _attrs.get(name);
assert (attr != null) : "Searching for a field that's not there: " + name;
_specifiedAttrs.add(attr);
}
private void done() {
if (_entity != null) {
Factory factory = (Factory)_entity;
factory.setCallback(0, null);
_entity = null;
}
if (_selects == null || _selects.size() == 0) {
_selectType = SelectType.Entity;
assert _entityBeanType.equals(_resultType) : "Expecting " + _entityBeanType + " because you didn't specify any selects but instead got " + _resultType;
return;
}
for (Select select : _selects) {
if (select.field == null) {
assert (_selects.size() == 1) : "You didn't specify any fields to put the result in but you're specifying more than one select so where should I put the selects?";
_selectType = SelectType.Single;
return;
}
if (select.func != null) {
_selectType = SelectType.Result;
return;
}
}
_selectType = SelectType.Fields;
}
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
String name = method.getName();
if (method.getAnnotation(Transient.class) == null) {
if (name.startsWith("get")) {
String fieldName = Character.toLowerCase(name.charAt(3)) + name.substring(4);
set(fieldName);
return null;
} else if (name.startsWith("is")) {
String fieldName = Character.toLowerCase(name.charAt(2)) + name.substring(3);
set(fieldName);
return null;
} else {
name = name.toLowerCase();
for (String fieldName : _attrs.keySet()) {
if (name.endsWith(fieldName.toLowerCase())) {
set(fieldName);
return null;
}
}
assert false : "Perhaps you need to make the method start with get or is?";
}
}
return methodProxy.invokeSuper(object, args);
}
@Override
public <K> K find() {
assert isSelectAll() : "find doesn't support select search";
done();
SearchCriteria sc1 = createSearchCriteria();
return (K)_dao.findOneBy(sc1);
}
}