Author: sdumitriu
Date: 2008-02-15 01:50:47 +0100 (Fri, 15 Feb 2008)
New Revision: 7739

Modified:
   
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/objects/classes/DBListClass.java
   
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/objects/classes/DBTreeListClass.java
Log:
XWIKI-2083: Improve the way DBList and DBTreeList generate queries
Done for DBTreeList, too
XWIKI-2120: DBList and DBTreeList queries should be just parsed, not rendered
Fixed.


Modified: 
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/objects/classes/DBListClass.java
===================================================================
--- 
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/objects/classes/DBListClass.java
   2008-02-15 00:50:21 UTC (rev 7738)
+++ 
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/objects/classes/DBListClass.java
   2008-02-15 00:50:47 UTC (rev 7739)
@@ -182,14 +182,6 @@
     {
         // First, get the hql query entered by the user.
         String sql = getSql();
-        try {
-            // TODO Why is it rendered? It is already parsed in the end, and I 
don't think it should
-            // also be rendered by Radeox.
-            sql = context.getDoc().getRenderedContent(sql, context);
-        } catch (Exception e) {
-            LOG.warn("Failed to render SQL script [" + sql + "]. Internal 
error ["
-                + e.getMessage() + "]. Continuing with non-rendered script.");
-        }
         // If the query field is blank, construct a query using the classname, 
idField and
         // valueField properties.
         if (StringUtils.isBlank(sql)) {
@@ -234,11 +226,10 @@
                 // The object is needed if there is a classname, or if at 
least one of the selected
                 // columns is an object property.
                 boolean usesObj =
-                    !StringUtils.isBlank(classname) || 
idField.startsWith("obj.")
-                        || valueField.startsWith("obj.");
+                    hasClassname || idField.startsWith("obj.") || 
valueField.startsWith("obj.");
                 // The document is needed if one of the selected columns is a 
document property, or
-                // if there is no classname specified and at least one of the 
selected columns is a
-                // document property.
+                // if there is no classname specified and at least one of the 
selected columns is
+                // not an object property.
                 boolean usesDoc = idField.startsWith("doc.") || 
valueField.startsWith("doc.");
                 if ((!idField.startsWith("obj.") || (hasValueField && 
!valueField
                     .startsWith("obj.")))
@@ -307,7 +298,13 @@
         }
         // Parse the query, so that it can contain velocity scripts, for 
example to use the
         // current document name, or the current username.
-        return context.getWiki().parseContent(sql, context);
+        try {
+            sql = context.getWiki().parseContent(sql, context);
+        } catch (Exception e) {
+            LOG.warn("Failed to parse SQL script [" + sql + "]. Internal error 
["
+                + e.getMessage() + "]. Continuing with non-rendered script.");
+        }
+        return sql;
     }
 
     public String getSql()

Modified: 
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/objects/classes/DBTreeListClass.java
===================================================================
--- 
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/objects/classes/DBTreeListClass.java
       2008-02-15 00:50:21 UTC (rev 7738)
+++ 
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/objects/classes/DBTreeListClass.java
       2008-02-15 00:50:47 UTC (rev 7739)
@@ -26,6 +26,7 @@
 import java.util.List;
 import java.util.Map;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.ecs.xhtml.option;
@@ -39,6 +40,9 @@
 import com.xpn.xwiki.objects.ListProperty;
 import com.xpn.xwiki.objects.meta.PropertyMetaClass;
 
+/**
+ * @version $Id: $
+ */
 public class DBTreeListClass extends DBListClass
 {
     private static final Log LOG = LogFactory.getLog(DBTreeListClass.class);
@@ -306,77 +310,190 @@
         buffer.append(select.toString());
     }
 
+    /**
+     * <p>
+     * Computes the query corresponding to the current XProperty. The query is 
either manually
+     * specified by the XClass creator in the <tt>sql</tt> field, or, if the 
query field is blank,
+     * constructed using the <tt>classname</tt>, <tt>idField</tt>, 
<tt>valueField</tt> and
+     * <tt>parentField</tt> properties. The query is constructed according to 
the following rules:
+     * </p>
+     * <ul>
+     * <li>If no classname, id and value fields are selected, return a query 
that return no rows,
+     * as the parent is not enough to make a query.</li>
+     * <li>If no parent field is provided, use the document "parent" 
medatada.</li>
+     * <li>If only the classname is provided, select all document names which 
have an object of
+     * that type, preserving the hierarchy defined by the parent field.</li>
+     * <li>If only one of id and value is provided, use it for both 
columns.</li>
+     * <li>If no classname is provided, assume the fields are document 
properties.</li>
+     * <li>If the document is not used at all, don't put it in the query.</li>
+     * <li>If the object is not used at all, don't put it in the query.</li>
+     * </ul>
+     * <p>
+     * The generated query always selects 3 columns, the first one is used as 
the stored value, the
+     * second one as the displayed value, and the third one defines the 
"parent" of the current
+     * value.
+     * </p>
+     * 
+     * @param context The current [EMAIL PROTECTED] XWikiContext context}.
+     * @return The HQL query corresponding to this property.
+     */
     public String getQuery(XWikiContext context)
     {
+        // First, get the hql query entered by the user.
         String sql = getSql();
-        try {
-            sql = context.getDoc().getRenderedContent(sql, context);
-        } catch (Exception e) {
-            LOG.warn("Failed to render SQL script [" + sql + "]. Internal 
error ["
-                + e.getMessage() + "]. Continuing with non-rendered script.");
-        }
-        if ((sql == null) || (sql.trim().equals(""))) {
-            String classname = getClassname();
-            String idField = getIdField();
-            String valueField = getValueField();
-            if ((valueField == null) || (valueField.trim().equals(""))) {
-                valueField = idField;
-            }
+        // If the query field is blank, construct a query using the classname, 
idField,
+        // valueField and parentField properties.
+        if (StringUtils.isBlank(sql)) {
             if (context.getWiki().getHibernateStore() != null) {
-                StringBuffer select = new StringBuffer("select ");
-                StringBuffer tables =
-                    new StringBuffer(" from XWikiDocument as doc, BaseObject 
as obj");
-                StringBuffer where =
-                    new StringBuffer(" where doc.fullName=obj.name and 
obj.className='");
-                where.append(classname).append("'");
+                // Extract the 3 properties in non-null variables.
+                String classname = StringUtils.defaultString(getClassname());
+                String idField = StringUtils.defaultString(getIdField());
+                String valueField = StringUtils.defaultString(getValueField());
+                String parentField = 
StringUtils.defaultString(getParentField());
 
+                // Check if the properties are specified or not.
+                boolean hasClassname = !StringUtils.isBlank(classname);
+                boolean hasIdField = !StringUtils.isBlank(idField);
+                boolean hasValueField = !StringUtils.isBlank(valueField);
+                boolean hasParentField = !StringUtils.isBlank(parentField);
+
+                if (!(hasIdField || hasValueField)) {
+                    // If only the classname is specified, return a query that 
selects all the
+                    // document names which have an object of that type, and 
the hierarchy is
+                    // defined by the document "parent" property (unless a 
parent property is
+                    // specified).
+                    if (hasClassname) {
+                        sql =
+                            "select distinct doc.fullName, doc.fullName, "
+                                + (hasParentField ? parentField : "doc.parent")
+                                + " from XWikiDocument as doc, BaseObject as 
obj"
+                                + " where doc.fullName=obj.name and 
obj.className='" + classname
+                                + "'";
+                    } else {
+                        // If none of the first 3 properties is specified, 
return a query that
+                        // always returns no rows (only with the parent field 
no query can be made)
+                        sql = DEFAULT_QUERY;
+                    }
+                    return sql;
+                }
+
+                // If only one of the id and value fields is specified, use it 
for both columns.
+                if (!hasIdField && hasValueField) {
+                    idField = valueField;
+                } else if (hasIdField && !hasValueField) {
+                    valueField = idField;
+                }
+
+                // If no parent field was specified, use the document "parent" 
metadata
+                if (!hasParentField) {
+                    parentField = "doc.parent";
+                }
+
+                // Check if the document and object are needed or not.
+                // The object is needed if there is a classname, or if at 
least one of the selected
+                // columns is an object property.
+                boolean usesObj =
+                    hasClassname || idField.startsWith("obj.") || 
valueField.startsWith("obj.")
+                        || parentField.startsWith("obj.");
+                // The document is needed if one of the selected columns is a 
document property, or
+                // if there is no classname specified and at least one of the 
selected columns is
+                // not an object property.
+                boolean usesDoc =
+                    idField.startsWith("doc.") || valueField.startsWith("doc.")
+                        || parentField.startsWith("doc.");
+                if ((!idField.startsWith("obj.") || 
!valueField.startsWith("obj.") || !parentField
+                    .startsWith("obj."))
+                    && !hasClassname) {
+                    usesDoc = true;
+                }
+
+                // Build the query in this variable.
+                StringBuffer select = new StringBuffer("select distinct ");
+                // These will hold the components of the from and where parts 
of the query.
+                ArrayList fromStatements = new ArrayList();
+                ArrayList whereStatements = new ArrayList();
+
+                // Add the document to the query only if it is needed.
+                if (usesDoc) {
+                    fromStatements.add("XWikiDocument as doc");
+                    if (usesObj) {
+                        whereStatements.add("doc.fullName=obj.name");
+                    }
+                }
+                // Add the object to the query only if it is needed.
+                if (usesObj) {
+                    fromStatements.add("BaseObject as obj");
+                    if (hasClassname) {
+                        whereStatements.add("obj.className='" + classname + 
"'");
+                    }
+                }
+
+                // Add the first column to the query.
                 if (idField.startsWith("doc.") || idField.startsWith("obj.")) {
                     select.append(idField);
+                } else if (!hasClassname) {
+                    select.append("doc." + idField);
                 } else {
                     select.append("idprop.value");
-                    tables.append(", StringProperty as idprop");
-                    where.append(" and obj.id=idprop.id.id and 
idprop.id.name='").append(idField)
-                        .append("'");
+                    fromStatements.add("StringProperty as idprop");
+                    whereStatements.add("obj.id=idprop.id.id and 
idprop.id.name='" + idField
+                        + "'");
                 }
 
+                // Add the second column to the query.
                 if (valueField.startsWith("doc.") || 
valueField.startsWith("obj.")) {
                     select.append(", ").append(valueField);
+                } else if (!hasClassname) {
+                    select.append(", doc." + valueField);
                 } else {
-                    if (idField.equals(valueField)) {
+                    if (valueField.equals(idField)) {
                         select.append(", idprop.value");
                     } else {
                         select.append(", valueprop.value");
-                        tables.append(", StringProperty as valueprop");
-                        where.append(" and obj.id=valueprop.id.id and 
valueprop.id.name='")
-                            .append(valueField).append("'");
+                        fromStatements.add("StringProperty as valueprop");
+                        whereStatements.add("obj.id=valueprop.id.id and 
valueprop.id.name='"
+                            + valueField + "'");
                     }
                 }
 
-                // DBTreeList specific part
-                String parentField = getParentField();
+                // Add the third column to the query.
                 if (parentField.startsWith("doc.") || 
parentField.startsWith("obj.")) {
                     select.append(", ").append(parentField);
+                } else if (!hasClassname) {
+                    select.append(", doc." + parentField);
                 } else {
-                    if (idField.equals(parentField)) {
+                    if (parentField.equals(idField)) {
                         select.append(", idprop.value");
-                    } else if (valueField.equals(parentField)) {
+                    } else if (parentField.equals(valueField)) {
                         select.append(", valueprop.value");
                     } else {
                         select.append(", parentprop.value");
-                        tables.append(", StringProperty as parentprop");
-                        where.append(" and obj.id=parentprop.id.id and 
parentprop.id.name='")
-                            .append(parentField).append("'");
+                        fromStatements.add("StringProperty as parentprop");
+                        whereStatements.add("obj.id=parentprop.id.id and 
parentprop.id.name='"
+                            + parentField + "'");
                     }
                 }
-
-                // Let's create the sql
-                sql = select.append(tables).append(where).toString();
+                // Let's create the complete query
+                select.append(" from ");
+                select.append(StringUtils.join(fromStatements.iterator(), ", 
"));
+                if (whereStatements.size() > 0) {
+                    select.append(" where ");
+                    select.append(StringUtils.join(whereStatements.iterator(), 
" and "));
+                }
+                sql = select.toString();
             } else {
                 // TODO: query plugin impl.
                 // We need to generate the right query for the query plugin
             }
-
         }
-        return context.getWiki().parseContent(sql, context);
+        // Parse the query, so that it can contain velocity scripts, for 
example to use the
+        // current document name, or the current username.
+        try {
+            sql = context.getWiki().parseContent(sql, context);
+        } catch (Exception e) {
+            LOG.warn("Failed to parse SQL script [" + sql + "]. Internal error 
["
+                + e.getMessage() + "]. Continuing with non-rendered script.");
+        }
+        return sql;
     }
 }

_______________________________________________
notifications mailing list
notifications@xwiki.org
http://lists.xwiki.org/mailman/listinfo/notifications

Reply via email to