Commit parsed filter feature contributed by Juerg Lehni.
This commit is contained in:
parent
f08e350367
commit
e45ef47dee
1 changed files with 162 additions and 8 deletions
|
@ -18,11 +18,13 @@ package helma.objectmodel.db;
|
|||
|
||||
import helma.framework.core.Application;
|
||||
import helma.objectmodel.INode;
|
||||
import helma.objectmodel.IProperty;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
|
@ -91,6 +93,8 @@ public final class Relation {
|
|||
String groupbyPrototype;
|
||||
String filter;
|
||||
String additionalTables;
|
||||
Vector filterFragments;
|
||||
Vector filterPropertyRefs;
|
||||
int maxSize = 0;
|
||||
|
||||
/**
|
||||
|
@ -107,6 +111,8 @@ public final class Relation {
|
|||
this.reftype = rel.reftype;
|
||||
this.order = rel.order;
|
||||
this.filter = rel.filter;
|
||||
this.filterFragments = rel.filterFragments;
|
||||
this.filterPropertyRefs = rel.filterPropertyRefs;
|
||||
this.additionalTables = rel.additionalTables;
|
||||
this.maxSize = rel.maxSize;
|
||||
this.constraints = rel.constraints;
|
||||
|
@ -262,17 +268,27 @@ public final class Relation {
|
|||
if (filter != null) {
|
||||
if (filter.trim().length() == 0) {
|
||||
filter = null;
|
||||
filterFragments = filterPropertyRefs = null;
|
||||
} else {
|
||||
// parenthesise filter
|
||||
filter = "("+filter+")";
|
||||
Vector fragments = new Vector();
|
||||
Vector propertyRefs = new Vector();
|
||||
parsePropertyString(filter, fragments, propertyRefs);
|
||||
// if no references where found, just use the filter string
|
||||
// otherwise use the filter fragments and proeprty refs instead
|
||||
if (propertyRefs.size() > 0) {
|
||||
filterFragments = fragments;
|
||||
filterPropertyRefs = propertyRefs;
|
||||
} else {
|
||||
filterFragments = filterPropertyRefs = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get additional tables
|
||||
additionalTables = props.getProperty(propName + ".filter.additionalTables");
|
||||
|
||||
if (additionalTables != null) {
|
||||
if (additionalTables.trim().length() == 0)
|
||||
if (additionalTables != null && additionalTables.trim().length() == 0) {
|
||||
additionalTables = null;
|
||||
}
|
||||
|
||||
|
@ -560,6 +576,77 @@ public final class Relation {
|
|||
return columnName;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is taken from org.apache.tools.ant ProjectHelper.java
|
||||
* distributed under the Apache Software License, Version 1.1
|
||||
*
|
||||
* Parses a string containing <code>${xxx}</code> style property
|
||||
* references into two lists. The first list is a collection
|
||||
* of text fragments, while the other is a set of string property names.
|
||||
* <code>null</code> entries in the first list indicate a property
|
||||
* reference from the second list.
|
||||
*
|
||||
* @param value Text to parse. Must not be <code>null</code>.
|
||||
* @param fragments List to add text fragments to.
|
||||
* Must not be <code>null</code>.
|
||||
* @param propertyRefs List to add property names to.
|
||||
* Must not be <code>null</code>.
|
||||
*/
|
||||
protected void parsePropertyString(String value, Vector fragments, Vector propertyRefs) {
|
||||
int prev = 0;
|
||||
int pos;
|
||||
//search for the next instance of $ from the 'prev' position
|
||||
while ((pos = value.indexOf("$", prev)) >= 0) {
|
||||
|
||||
//if there was any text before this, add it as a fragment
|
||||
//TODO, this check could be modified to go if pos>prev;
|
||||
//seems like this current version could stick empty strings
|
||||
//into the list
|
||||
if (pos > 0) {
|
||||
fragments.addElement(value.substring(prev, pos));
|
||||
}
|
||||
//if we are at the end of the string, we tack on a $
|
||||
//then move past it
|
||||
if (pos == (value.length() - 1)) {
|
||||
fragments.addElement("$");
|
||||
prev = pos + 1;
|
||||
} else if (value.charAt(pos + 1) != '{') {
|
||||
//peek ahead to see if the next char is a property or not
|
||||
//not a property: insert the char as a literal
|
||||
/*
|
||||
fragments.addElement(value.substring(pos + 1, pos + 2));
|
||||
prev = pos + 2;
|
||||
*/
|
||||
if (value.charAt(pos + 1) == '$') {
|
||||
//backwards compatibility two $ map to one mode
|
||||
fragments.addElement("$");
|
||||
prev = pos + 2;
|
||||
} else {
|
||||
//new behaviour: $X maps to $X for all values of X!='$'
|
||||
fragments.addElement(value.substring(pos, pos + 2));
|
||||
prev = pos + 2;
|
||||
}
|
||||
|
||||
} else {
|
||||
//property found, extract its name or bail on a typo
|
||||
int endName = value.indexOf('}', pos);
|
||||
if (endName < 0) {
|
||||
throw new RuntimeException("Syntax error in property: "
|
||||
+ value);
|
||||
}
|
||||
String propertyName = value.substring(pos + 2, endName);
|
||||
fragments.addElement(null);
|
||||
propertyRefs.addElement(propertyName);
|
||||
prev = endName + 1;
|
||||
}
|
||||
}
|
||||
//no more $ signs found
|
||||
//if there is any tail to the file, append it
|
||||
if (prev < value.length()) {
|
||||
fragments.addElement(value.substring(prev));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get a DbMapping to use for virtual aka collection nodes.
|
||||
*/
|
||||
|
@ -701,8 +788,7 @@ public final class Relation {
|
|||
}
|
||||
|
||||
if (filter != null) {
|
||||
q.append(prefix);
|
||||
q.append(filter);
|
||||
appendFilter(q, nonvirtual, prefix);
|
||||
}
|
||||
|
||||
if (groupby != null) {
|
||||
|
@ -718,6 +804,75 @@ public final class Relation {
|
|||
return q.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the filter.
|
||||
*/
|
||||
protected void appendFilter(StringBuffer q, INode nonvirtual, String prefix) throws SQLException {
|
||||
q.append(prefix);
|
||||
q.append('(');
|
||||
if (filterFragments == null) {
|
||||
q.append(filter);
|
||||
} else {
|
||||
Enumeration i = filterFragments.elements();
|
||||
Enumeration j = filterPropertyRefs.elements();
|
||||
while (i.hasMoreElements()) {
|
||||
String fragment = (String) i.nextElement();
|
||||
if (fragment == null) {
|
||||
/*
|
||||
// begin property version
|
||||
String propertyName = (String) j.nextElement();
|
||||
Object value = null;
|
||||
if (propertyName != null) {
|
||||
if (propertyName.equals("__id__") || propertyName.equals("_id")) {
|
||||
value = nonvirtual.getID();
|
||||
} else if (propertyName.equals("__name__")) {
|
||||
value = nonvirtual.getName();
|
||||
} else if (propertyName.equals("__prototype__") || propertyName.equals("_prototype")) {
|
||||
value = nonvirtual.getPrototype();
|
||||
} else {
|
||||
IProperty property = nonvirtual.get(propertyName);
|
||||
if (property != null) {
|
||||
value = property.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
// end property version
|
||||
*/
|
||||
// begin column version
|
||||
String columnName = (String) j.nextElement();
|
||||
Object value = null;
|
||||
if (columnName != null) {
|
||||
DbMapping dbmap = nonvirtual.getDbMapping();
|
||||
if (columnName.equals(dbmap.getIDField())) {
|
||||
value = nonvirtual.getID();
|
||||
} else if (columnName.equals(dbmap.getNameField())) {
|
||||
value = nonvirtual.getName();
|
||||
} else if (columnName.equals(dbmap.getPrototypeField())) {
|
||||
value = nonvirtual.getPrototype();
|
||||
} else {
|
||||
String propertyName = dbmap.columnNameToProperty(columnName);
|
||||
if (propertyName != null) {
|
||||
IProperty property = nonvirtual.get(propertyName);
|
||||
if (property != null) {
|
||||
value = property.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// end column version
|
||||
if (value != null) {
|
||||
q.append(escape(value.toString()));
|
||||
} else {
|
||||
q.append("NULL");
|
||||
}
|
||||
} else {
|
||||
q.append(fragment);
|
||||
}
|
||||
}
|
||||
}
|
||||
q.append(')');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
|
@ -739,10 +894,9 @@ public final class Relation {
|
|||
}
|
||||
|
||||
if (filter != null) {
|
||||
q.append(prefix);
|
||||
q.append(filter);
|
||||
appendFilter(q, nonvirtual, prefix);
|
||||
}
|
||||
|
||||
|
||||
return q.toString();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue