diff --git a/server/test/com/cloud/agent/manager/SearchCriteria2Test.java b/server/test/com/cloud/agent/manager/SearchCriteria2Test.java index c3e455229a8..ac5f8b2d3c3 100755 --- a/server/test/com/cloud/agent/manager/SearchCriteria2Test.java +++ b/server/test/com/cloud/agent/manager/SearchCriteria2Test.java @@ -6,6 +6,7 @@ import org.apache.log4j.Logger; import org.junit.After; import org.junit.Before; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; @@ -51,7 +52,6 @@ public class SearchCriteria2Test extends TestCase { s_logger.info("Host id: " + vo.getId() + " is Disconnected"); } - SearchCriteria2 sc1 = SearchCriteria2.create(VMInstanceVO.class); sc1.addAnd(sc1.getEntity().getState(), Op.EQ, VirtualMachine.State.Running); List vms = sc1.list(); @@ -59,6 +59,14 @@ public class SearchCriteria2Test extends TestCase { s_logger.info("Vm name:" + vm.getInstanceName()); } + SearchCriteria2 sc3 = SearchCriteria2.create(HostVO.class, Long.class); + sc3.selectField(sc3.getEntity().getId()); + sc3.addAnd(sc3.getEntity().getStatus(), Op.EQ, Status.Disconnected); + sc3.addAnd(sc3.getEntity().getType(), Op.EQ, Host.Type.Routing); + List hostIds = sc3.list(); + for (Long id : hostIds) { + s_logger.info("Host Id is " + id); + } } @Override diff --git a/utils/src/com/cloud/utils/db/GenericDao.java b/utils/src/com/cloud/utils/db/GenericDao.java index 274288c21bd..b0be46ec729 100755 --- a/utils/src/com/cloud/utils/db/GenericDao.java +++ b/utils/src/com/cloud/utils/db/GenericDao.java @@ -236,5 +236,9 @@ public interface GenericDao { boolean lockInLockTable(String id, int seconds); boolean unlockFromLockTable(String id); + + SearchCriteria2 createSearchCriteria2(Class resultType); + + SearchCriteria2 createSearchCriteria2(); } \ No newline at end of file diff --git a/utils/src/com/cloud/utils/db/GenericDaoBase.java b/utils/src/com/cloud/utils/db/GenericDaoBase.java index 6302c6bd817..d8b06b88d74 100755 --- a/utils/src/com/cloud/utils/db/GenericDaoBase.java +++ b/utils/src/com/cloud/utils/db/GenericDaoBase.java @@ -1653,5 +1653,22 @@ public abstract class GenericDaoBase implements Gene SearchBuilder builder = createSearchBuilder(); return builder.create(); } - + + @Override @DB(txn=false) + public SearchCriteria2 createSearchCriteria2(Class resultType) { + final T entity = (T)_searchEnhancer.create(); + final Factory factory = (Factory)entity; + SearchCriteria2 sc = new SearchCriteria2(entity, resultType, _allAttributes, this); + factory.setCallback(0, sc); + return sc; + } + + @Override @DB(txn=false) + public SearchCriteria2 createSearchCriteria2() { + final T entity = (T)_searchEnhancer.create(); + final Factory factory = (Factory)entity; + SearchCriteria2 sc = new SearchCriteria2(entity, (Class)entity.getClass(), _allAttributes, this); + factory.setCallback(0, sc); + return sc; + } } diff --git a/utils/src/com/cloud/utils/db/SearchCriteria.java b/utils/src/com/cloud/utils/db/SearchCriteria.java index 00abb3a1606..8b0e1b1bd36 100755 --- a/utils/src/com/cloud/utils/db/SearchCriteria.java +++ b/utils/src/com/cloud/utils/db/SearchCriteria.java @@ -115,7 +115,7 @@ public class SearchCriteria { private final Map _attrs; private final ArrayList _conditions; private ArrayList _additionals = null; - private final HashMap _params = new HashMap(); + private HashMap _params = new HashMap(); private int _counter; private HashMap>> _joins; private final ArrayList selects, SelectType selectType, Class resultType, HashMap params) { + this._attrs = attrs; + this._conditions = conditions; + this._selects = selects; + this._selectType = selectType; + this._resultType = resultType; + this._params = params; + this._builder = null; + this._additionals = new ArrayList(); + this._counter = 0; + this._joins = null; + this._groupBy = null; + this._groupByValues = null; + } + protected SearchCriteria(GenericSearchBuilder sb) { this._builder = null; this._attrs = sb._attrs; diff --git a/utils/src/com/cloud/utils/db/SearchCriteria2.java b/utils/src/com/cloud/utils/db/SearchCriteria2.java index d685f3dec96..e08caf1720f 100755 --- a/utils/src/com/cloud/utils/db/SearchCriteria2.java +++ b/utils/src/com/cloud/utils/db/SearchCriteria2.java @@ -1,42 +1,188 @@ 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; -public class SearchCriteria2 extends SearchCriteria { - GenericSearchBuilder _sb; +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 implements SearchCriteriaService, MethodInterceptor{ GenericDao _dao; + final protected Map _attrs; + protected ArrayList _specifiedAttrs; + protected T _entity; + protected ArrayList _conditions; + protected ArrayList(); + } + + 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(); - _sb.and(uuid, null, op); - this.setParameters(uuid, values); + constructCondition(uuid, " AND ", _specifiedAttrs.get(0), op); + setParameters(uuid, values); } + @Override public List list() { - return (List)_dao.search((SearchCriteria)this, null); + done(); + SearchCriteria sc1 = createSearchCriteria(); + if (isSelectAll()) { + return (List)_dao.search(sc1, null); + } else { + return (List)_dao.customSearch(sc1, null); + } } + private boolean isSelectAll() { + return _selects == null || _selects.size() == 0; + } + public T getEntity() { - return (T) _sb.entity(); + return (T) _entity; } + + private SearchCriteria createSearchCriteria() { + return new SearchCriteria(_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); + } + } diff --git a/utils/src/com/cloud/utils/db/SearchCriteriaService.java b/utils/src/com/cloud/utils/db/SearchCriteriaService.java new file mode 100755 index 00000000000..d4bbc593d89 --- /dev/null +++ b/utils/src/com/cloud/utils/db/SearchCriteriaService.java @@ -0,0 +1,11 @@ +package com.cloud.utils.db; + +import java.util.List; + +import com.cloud.utils.db.SearchCriteria.Op; + +public interface SearchCriteriaService { + public void selectField(Object... useless); + public void addAnd(Object useless, Op op, Object...values); + public List list(); +}