2 * Copyright (C) 2011 Openismus GmbH
4 * This file is part of GWT-Glom.
6 * GWT-Glom is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
11 * GWT-Glom is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with GWT-Glom. If not, see <http://www.gnu.org/licenses/>.
20 package org.glom.web.server.database;
22 import java.sql.Connection;
23 import java.util.ArrayList;
25 import org.apache.commons.lang3.StringUtils;
26 import org.glom.libglom.Field;
27 import org.glom.libglom.FieldVector;
28 import org.glom.libglom.LayoutGroupVector;
29 import org.glom.libglom.LayoutItem_Portal;
30 import org.glom.libglom.Relationship;
31 import org.glom.libglom.SortClause;
32 import org.glom.libglom.Value;
33 import org.glom.web.server.Log;
34 import org.glom.web.server.SqlUtils;
35 import org.glom.web.server.Utils;
36 import org.glom.web.shared.DataItem;
37 import org.glom.web.shared.TypedDataItem;
38 import org.jooq.Condition;
39 import org.glom.web.shared.libglom.Document;
41 import com.mchange.v2.c3p0.ComboPooledDataSource;
46 public class RelatedListDBAccess extends ListDBAccess {
47 private TypedDataItem foreignKeyValue = null;
48 private LayoutItem_Portal portal = null;
49 private String parentTable = null;
50 private String whereClauseToTableName = null;
51 private Field whereClauseToKeyField = null;
53 public RelatedListDBAccess(final Document document, final String documentID, final ComboPooledDataSource cpds,
54 final String tableName, final String relationshipName) {
55 super(document, documentID, cpds, tableName);
57 final LayoutItem_Portal portal = getPortal(relationshipName);
59 Log.error(documentID, tableName, "Couldn't find LayoutItem_Portal \"" + relationshipName + "\" in table \""
60 + tableName + "\". " + "Cannot retrive data for the related list.");
64 parentTable = tableName;
65 // Reassign the tableName variable to table that is being used for the related list. This needs to be set before
66 // getFieldsToShowForSQLQuery().
67 this.tableName = portal.get_table_used("" /* parent table - not relevant */);
69 // Convert the libglom LayoutGroup object into a LayoutFieldVector suitable for SQL queries.
70 final LayoutGroupVector tempLayoutGroupVec = new LayoutGroupVector();
71 tempLayoutGroupVec.add(portal);
72 fieldsToGet = getFieldsToShowForSQLQuery(tempLayoutGroupVec);
75 * The code from the rest of this method was inspired by code from Glom:
76 * Base_DB::set_found_set_where_clause_for_portal()
78 final Relationship relationship = portal.get_relationship();
80 // Notice that, in the case that this is a portal to doubly-related records,
81 // The WHERE clause mentions the first-related table (though by the alias defined in extra_join)
82 // and we add an extra JOIN to mention the second-related table.
84 whereClauseToTableName = relationship.get_to_table();
85 whereClauseToKeyField = getFieldInTable(relationship.get_to_field(), whereClauseToTableName);
88 fieldsToGet.add(getPrimaryKeyLayoutItemField(this.tableName));
90 final Relationship relationshipRelated = portal.get_related_relationship();
91 if (relationshipRelated != null) {
92 Log.error(documentID, tableName, "The related relationship " + relationshipRelated.get_name()
93 + " is not empty but the related relationship code has not been implemented yet.");
95 // FIXME port this Glom code to Java
99 sharedptr<UsesRelationship> uses_rel_temp = sharedptr<UsesRelationship>::create();
100 uses_rel_temp->set_relationship(relationship);
101 found_set.m_extra_join = relationship;
103 //Adjust the WHERE clause appropriately for the extra JOIN:
104 whereClauseToTableName = uses_rel_temp->get_sql_join_alias_name();
106 const Glib::ustring to_field_name = uses_rel_temp->get_to_field_used();
107 where_clause_to_key_field = get_fields_for_table_one_field(relationship->get_to_table(), to_field_name);
108 std::cout << "extra_join=" << found_set.m_extra_join << std::endl;
109 std::cout << "extra_join where_clause_to_key_field=" << where_clause_to_key_field->get_name() << std::endl;
115 this.portal = portal;
119 public ArrayList<DataItem[]> getData(final int start, final int length, final TypedDataItem foreignKeyValue,
120 final boolean useSortClause, final int sortColumnIndex, final boolean isAscending) {
122 if (tableName == null || foreignKeyValue == null || foreignKeyValue.isEmpty()) {
126 // Set the foreignKeyValue
127 this.foreignKeyValue = foreignKeyValue;
129 return getListData("" /* quickFind */, start, length, useSortClause, sortColumnIndex, isAscending);
135 * @see org.glom.web.server.ListDBAccess#getExpectedResultSize()
137 public int getExpectedResultSize(final TypedDataItem foreignKeyValue) {
139 // Set the foreignKeyValue
140 this.foreignKeyValue = foreignKeyValue;
142 if (fieldsToGet == null || fieldsToGet.size() <= 0 || this.foreignKeyValue == null)
145 return getResultSizeOfSQLQuery();
151 * @see org.glom.web.server.ListDBAccess#getSelectQuery(org.glom.libglom.LayoutFieldVector,
152 * org.glom.libglom.SortClause)
155 protected String getSelectQuery(final Connection connection, final String quickFind, final SortClause sortClause) {
156 // TODO: combine this method with getCountQuery() to remove duplicate code
157 if (portal == null) {
158 Log.error(documentID, parentTable,
159 "The Portal has not been found. Cannot build query for the related list.");
163 if (foreignKeyValue == null || foreignKeyValue.isEmpty()) {
164 Log.error(documentID, parentTable,
165 "The value for the foreign key has not been set. Cannot build query for the related list.");
169 Condition whereClause = null; // Note that we ignore quickFind.
170 // only attempt to make a where clause if it makes sense to do so
171 if (!StringUtils.isEmpty(whereClauseToTableName)) {
172 final Value gdaForeignKeyValue = Utils.getGlomTypeGdaValueForTypedDataItem(documentID, tableName,
173 whereClauseToKeyField.get_glom_type(), foreignKeyValue);
174 if (gdaForeignKeyValue != null)
175 whereClause = SqlUtils.build_simple_where_expression(whereClauseToTableName, whereClauseToKeyField,
179 return SqlUtils.build_sql_select_with_where_clause(connection, tableName, fieldsToGet, whereClause, sortClause);
183 private Field getFieldInTable(final String fieldName, final String tableName) {
185 if (StringUtils.isEmpty(tableName))
188 final FieldVector fields = document.get_table_fields(tableName);
189 for (int i = 0; i < fields.size(); i++) {
190 final Field field = fields.get(i);
191 if (fieldName.equals(field.get_name())) {
202 * @see org.glom.web.server.ListDBAccess#getCountQuery()
205 protected String getCountQuery(final Connection connection) {
206 // TODO: combine this method with getSelectQuery() to remove duplicate code
207 if (portal == null) {
208 Log.error(documentID, parentTable,
209 "The Portal has not been found. Cannot build query for the related list.");
213 if (foreignKeyValue == null || foreignKeyValue.isEmpty()) {
214 Log.error(documentID, parentTable,
215 "The value for the foreign key has not been set. Cannot build query for the related list.");
219 Condition whereClause = null;
220 // only attempt to make a where clause if it makes sense to do so
221 if (!whereClauseToTableName.isEmpty() && whereClauseToKeyField != null) {
222 final Value gdaForeignKeyValue = Utils.getGlomTypeGdaValueForTypedDataItem(documentID, tableName,
223 whereClauseToKeyField.get_glom_type(), foreignKeyValue);
224 if (gdaForeignKeyValue != null)
225 whereClause = SqlUtils.build_simple_where_expression(whereClauseToTableName, whereClauseToKeyField,
229 return SqlUtils.build_sql_count_select_with_where_clause(connection, tableName, fieldsToGet, whereClause);