You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@labs.apache.org by si...@apache.org on 2010/01/04 13:27:35 UTC

svn commit: r895613 - in /labs/magma/trunk/foundation-database/src: main/java/org/apache/magma/database/QueryByExampleBean.java main/java/org/apache/magma/database/QueryByExampleBuilder.java test/java/org/apache/magma/database/TestQbe.java

Author: simoneg
Date: Mon Jan  4 12:27:35 2010
New Revision: 895613

URL: http://svn.apache.org/viewvc?rev=895613&view=rev
Log:
QBE now supports query customization via an interface

Added:
    labs/magma/trunk/foundation-database/src/main/java/org/apache/magma/database/QueryByExampleBean.java
Modified:
    labs/magma/trunk/foundation-database/src/main/java/org/apache/magma/database/QueryByExampleBuilder.java
    labs/magma/trunk/foundation-database/src/test/java/org/apache/magma/database/TestQbe.java

Added: labs/magma/trunk/foundation-database/src/main/java/org/apache/magma/database/QueryByExampleBean.java
URL: http://svn.apache.org/viewvc/labs/magma/trunk/foundation-database/src/main/java/org/apache/magma/database/QueryByExampleBean.java?rev=895613&view=auto
==============================================================================
--- labs/magma/trunk/foundation-database/src/main/java/org/apache/magma/database/QueryByExampleBean.java (added)
+++ labs/magma/trunk/foundation-database/src/main/java/org/apache/magma/database/QueryByExampleBean.java Mon Jan  4 12:27:35 2010
@@ -0,0 +1,18 @@
+package org.apache.magma.database;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.magma.database.QueryByExampleBuilder.FieldSettings;
+
+public interface QueryByExampleBean {
+
+	public class QueryPart {
+		public String join;
+		public String clause;
+		public List<Object> params = new ArrayList<Object>();
+	}
+	
+	public QueryPart modifyQueryFor(String field, FieldSettings settings);
+	
+}

Modified: labs/magma/trunk/foundation-database/src/main/java/org/apache/magma/database/QueryByExampleBuilder.java
URL: http://svn.apache.org/viewvc/labs/magma/trunk/foundation-database/src/main/java/org/apache/magma/database/QueryByExampleBuilder.java?rev=895613&r1=895612&r2=895613&view=diff
==============================================================================
--- labs/magma/trunk/foundation-database/src/main/java/org/apache/magma/database/QueryByExampleBuilder.java (original)
+++ labs/magma/trunk/foundation-database/src/main/java/org/apache/magma/database/QueryByExampleBuilder.java Mon Jan  4 12:27:35 2010
@@ -15,6 +15,7 @@
 
 import org.apache.commons.beanutils.MethodUtils;
 import org.apache.magma.basics.MagmaException;
+import org.apache.magma.database.QueryByExampleBean.QueryPart;
 
 public class QueryByExampleBuilder<T> {
 
@@ -45,8 +46,15 @@
 	public void addIgnore(String field) {
 		this.ignoreds.add(field);
 	}
-	
 	public Query generateQuery(T qbe) {
+		return generateQuery(qbe, qbe.getClass());
+	}
+
+	
+	public Query generateQuery(T qbe, Class targetClass) {
+		QueryByExampleBean qbeb = null;
+		if (qbe instanceof QueryByExampleBean) qbeb = (QueryByExampleBean) qbe;
+		StringBuilder fromb = new StringBuilder();
 		StringBuilder sb = new StringBuilder();
 		boolean wheresent = false;
 		List<Object> params = new ArrayList<Object>();
@@ -68,80 +76,105 @@
 				}
 				if (settings == null) settings = this.defaults;
 				String clause = "";
-				if (type.equals(String.class)) {
-					String val = (String) rm.invoke(qbe);
-					if (val == null || val.length() == 0) continue;
-					boolean like = false;
-					if (settings.getStartsLike()) {
-						val = val + "%";
-						like = true;
-					} else if (settings.getContainsLike() || settings.getKeywordsLike()) {
-						val = "%" + val + "%";
-						like = true;
-					}
-					if (settings.getKeywordsLike()) {
-						val = val.replace(' ', '%');
-						like = true;
-					}
-					clause = "x." + name;
-					if (!settings.getCaseSensitive()) {
-						clause = "LOWER(" + clause + ")";
-						val = val.toLowerCase();
-					}
-					if (like) {
-						clause += " LIKE ";
+				QueryPart part = null;
+				if (qbeb != null) part = qbeb.modifyQueryFor(name, settings);
+				if (qbeb == null || part == null) {
+					if (type.equals(String.class)) {
+						String val = (String) rm.invoke(qbe);
+						if (val == null || val.length() == 0) continue;
+						boolean like = false;
+						if (settings.getStartsLike()) {
+							val = val + "%";
+							like = true;
+						} else if (settings.getContainsLike() || settings.getKeywordsLike()) {
+							val = "%" + val + "%";
+							like = true;
+						}
+						if (settings.getKeywordsLike()) {
+							val = val.replace(' ', '%');
+							like = true;
+						}
+						clause = "x." + name;
+						if (!settings.getCaseSensitive()) {
+							clause = "LOWER(" + clause + ")";
+							val = val.toLowerCase();
+						}
+						if (like) {
+							clause += " LIKE ";
+						} else {
+							clause += " = ";
+						}
+						clause += "?" + (params.size() + 1);
+						params.add(val);						
+					} else if (Number.class.isAssignableFrom(type)) {
+						Number val = (Number)rm.invoke(qbe);
+						if (val == null) continue;
+						if (!settings.getConsiderZero() && val.intValue() == 0) continue;
+						clause = "x." + name;
+						clause += "=?" + (params.size() + 1);
+						params.add(val);
+					} else if (Date.class.isAssignableFrom(type)) {
+						// Try to create a range around meaningful part of a date.
+						Date val = (Date) rm.invoke(qbe);
+						if (val == null) continue;
+						GregorianCalendar calendar = new GregorianCalendar();
+						calendar.setTime(val);
+						for (int calele : new int[] {
+								GregorianCalendar.MILLISECOND,
+								GregorianCalendar.SECOND,
+								GregorianCalendar.MINUTE,
+								GregorianCalendar.HOUR_OF_DAY,
+								GregorianCalendar.DAY_OF_MONTH,
+								GregorianCalendar.MONTH
+							}) {
+							if (calendar.get(calele) == calendar.getActualMinimum(calele)) {
+								calendar.set(calele, calendar.getActualMaximum(calele));
+							}
+						}
+						clause = "(x." + name + ">=";
+						clause += "?" + (params.size() + 1);
+						params.add(val);	
+						clause += " AND x." + name + "<=";
+						clause += "?" + (params.size() + 1) + ")";
+						params.add(calendar.getTime());	
 					} else {
-						clause += " = ";
-					}
-					clause += "?" + (params.size() + 1);
-					params.add(val);
-				} else if (Number.class.isAssignableFrom(type)) {
-					Number val = (Number)rm.invoke(qbe);
-					if (val == null) continue;
-					if (!settings.getConsiderZero() && val.intValue() == 0) continue;
-					clause = "x." + name;
-					clause += "=?" + (params.size() + 1);
-					params.add(val);	
-				} else if (Date.class.isAssignableFrom(type)) {
-					// Try to create a range around meaningful part of a date.
-					Date val = (Date) rm.invoke(qbe);
-					if (val == null) continue;
-					GregorianCalendar calendar = new GregorianCalendar();
-					calendar.setTime(val);
-					for (int calele : new int[] {
-							GregorianCalendar.MILLISECOND,
-							GregorianCalendar.SECOND,
-							GregorianCalendar.MINUTE,
-							GregorianCalendar.HOUR_OF_DAY,
-							GregorianCalendar.DAY_OF_MONTH,
-							GregorianCalendar.MONTH
-						}) {
-						if (calendar.get(calele) == calendar.getActualMinimum(calele)) {
-							calendar.set(calele, calendar.getActualMaximum(calele));
+						Object val = rm.invoke(qbe);
+						if (val == null) continue;
+						clause = "x." + name;
+						clause += "=?" + (params.size() + 1);
+						params.add(val);
+					}
+					if (clause != null) {
+						if (wheresent) {
+							sb.append(this.useOr ? " OR " : " AND ");
+						} else {
+							sb.append(" WHERE ");
+							wheresent = true;
 						}
+						sb.append(clause);
 					}
-					clause = "(x." + name + ">=";
-					clause += "?" + (params.size() + 1);
-					params.add(val);	
-					clause += " AND x." + name + "<=";
-					clause += "?" + (params.size() + 1) + ")";
-					params.add(calendar.getTime());	
-					
 				} else {
-					Object val = rm.invoke(qbe);
-					if (val == null) continue;
-					clause = "x." + name;
-					clause += "=?" + (params.size() + 1);
-					params.add(val);								
-				}
-				if (clause != null) {
+					if (part.join != null && part.join.length() > 0) {
+						if (fromb.length() == 0) {
+							fromb.append("FROM ");
+							fromb.append(targetClass.getName());
+							fromb.append(" x ");
+						}
+						fromb.append(",");
+						fromb.append(part.join);
+					}
+					String pcl = part.clause;
+					for (int i = 0; i < part.params.size(); i++) {
+						params.add(part.params.get(i));
+						pcl = pcl.replaceAll("\\?" + (i + 1), "?" + (params.size()));
+					}
 					if (wheresent) {
 						sb.append(this.useOr ? " OR " : " AND ");
 					} else {
 						sb.append(" WHERE ");
 						wheresent = true;
 					}
-					sb.append(clause);
+					sb.append(pcl);
 				}
 			}
 		} catch (Exception e) {
@@ -149,12 +182,15 @@
 		}
 		
 		Query ret = new Query();
+		if (fromb.length() > 0)
+			ret.from = fromb.toString(); 
 		ret.query = sb.toString();
 		ret.params = params.toArray();
 		return ret;
 	}
 	
 	public class Query {
+		public String from;
 		public String query;
 		public Object[] params;
 	}

Modified: labs/magma/trunk/foundation-database/src/test/java/org/apache/magma/database/TestQbe.java
URL: http://svn.apache.org/viewvc/labs/magma/trunk/foundation-database/src/test/java/org/apache/magma/database/TestQbe.java?rev=895613&r1=895612&r2=895613&view=diff
==============================================================================
--- labs/magma/trunk/foundation-database/src/test/java/org/apache/magma/database/TestQbe.java (original)
+++ labs/magma/trunk/foundation-database/src/test/java/org/apache/magma/database/TestQbe.java Mon Jan  4 12:27:35 2010
@@ -7,6 +7,7 @@
 import java.util.Date;
 import java.util.GregorianCalendar;
 
+import org.apache.magma.database.QueryByExampleBuilder.FieldSettings;
 import org.apache.magma.database.QueryByExampleBuilder.Query;
 import static org.apache.magma.testing.AssertStringStructure.assertStructure;
 import org.junit.Test;
@@ -103,11 +104,87 @@
 		assertThat(query.params.length, equalTo(2));
 		assertStructure(query.query, "WHERE", "x.birthday", ">=", "?1", "AND", "x.birthday", "<=", "?2", ")", "$$");
 		assertThat((Date)query.params[0], equalTo(cal.getTime()));
+		cal.setTime((Date) query.params[0]);
+		assertThat(cal.get(GregorianCalendar.YEAR), equalTo(1979));
+		assertThat(cal.get(GregorianCalendar.MONTH), equalTo(GregorianCalendar.MARCH));
+		assertThat(cal.get(GregorianCalendar.DAY_OF_MONTH), equalTo(5));
+		assertThat(cal.get(GregorianCalendar.HOUR_OF_DAY), equalTo(0));
+		assertThat(cal.get(GregorianCalendar.MINUTE), equalTo(0));
+		assertThat(cal.get(GregorianCalendar.SECOND), equalTo(0));
+		assertThat(cal.get(GregorianCalendar.MILLISECOND), equalTo(0));
 		cal.setTime((Date) query.params[1]);
+		assertThat(cal.get(GregorianCalendar.YEAR), equalTo(1979));
+		assertThat(cal.get(GregorianCalendar.MONTH), equalTo(GregorianCalendar.MARCH));
+		assertThat(cal.get(GregorianCalendar.DAY_OF_MONTH), equalTo(5));
 		assertThat(cal.get(GregorianCalendar.HOUR_OF_DAY), equalTo(23));
 		assertThat(cal.get(GregorianCalendar.MINUTE), equalTo(59));
 		assertThat(cal.get(GregorianCalendar.SECOND), equalTo(59));
 		assertThat(cal.get(GregorianCalendar.MILLISECOND), equalTo(999));
 	}
 	
+	@Test
+	public void qbeBean() throws Exception {
+		
+		class SpecificBean implements QueryByExampleBean {
+			private String name;
+			private String state;
+			
+			public String getName() {
+				return name;
+			}
+			public void setName(String name) {
+				this.name = name;
+			}
+			public String getState() {
+				return state;
+			}
+			public void setState(String state) {
+				this.state = state;
+			}
+			
+			public QueryPart modifyQueryFor(String field, FieldSettings settings) {
+				if (field.equals("state") && this.getState() != null) {
+					QueryPart ret = new QueryPart();
+					ret.join = "LEFT JOIN x.locations location";
+					ret.clause = "location.state=?1";
+					ret.params.add(this.getState());
+					return ret;
+				}
+				return null;
+			}
+		}
+		
+		SpecificBean sb = new SpecificBean();
+		QueryByExampleBuilder<SpecificBean> qbe = new QueryByExampleBuilder<SpecificBean>();
+		Query query = qbe.generateQuery(sb);
+		System.out.println(query.query);
+		assertThat(query.params.length, equalTo(0));
+		assertStructure(query.query, "!!WHERE");
+		
+		sb.name = "foo";
+		query = qbe.generateQuery(sb);
+		System.out.println(query.query);
+		assertThat(query.params.length, equalTo(1));
+		assertStructure(query.query, "WHERE", "LOWER(x.name)", "LIKE", "?1", "$$");
+		
+		sb.name=null;
+		sb.state = "Alabama";
+		query = qbe.generateQuery(sb);
+		System.out.println(query.from);
+		System.out.println(query.query);
+		assertThat(query.params.length, equalTo(1));
+		assertStructure(query.from, "FROM", SpecificBean.class.getName(), "x", "LEFT JOIN", "x.locations", "location", "$$");
+		assertStructure(query.query, "WHERE", "location.state", "=", "?1", "$$");
+
+		sb.name="foo";
+		sb.state = "Alabama";
+		query = qbe.generateQuery(sb);
+		System.out.println(query.from);
+		System.out.println(query.query);
+		assertThat(query.params.length, equalTo(2));
+		assertStructure(query.from, "FROM", SpecificBean.class.getName(), "x", "LEFT JOIN", "x.locations", "location", "$$");
+		assertStructure(query.query, "WHERE", "x.name", "?1", "location.state", "=", "?2", "$$");
+
+	}
+	
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org