Add navigation buttons to related list tables.
[online-glom:gwt-glom.git] / src / main / java / org / glom / web / server / database / RelatedListDBAccess.java
1 /*
2  * Copyright (C) 2011 Openismus GmbH
3  *
4  * This file is part of GWT-Glom.
5  *
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.
10  *
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
14  * for more details.
15  *
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/>.
18  */
19
20 package org.glom.web.server.database;
21
22 import java.util.ArrayList;
23
24 import org.glom.libglom.Document;
25 import org.glom.libglom.Field;
26 import org.glom.libglom.FieldVector;
27 import org.glom.libglom.Glom;
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.web.server.Log;
33 import org.glom.web.shared.DataItem;
34
35 import com.mchange.v2.c3p0.ComboPooledDataSource;
36
37 /**
38  * @author Ben Konrath <ben@bagu.org>
39  */
40 public class RelatedListDBAccess extends ListDBAccess {
41         private String foreignKeyValue = null;
42         private LayoutItem_Portal portal = null;
43         private String parentTable = null;
44         private String whereClauseToTableName = null;
45         private Field whereClauseToKeyField = null;
46
47         public RelatedListDBAccess(Document document, String documentID, ComboPooledDataSource cpds, String tableName,
48                         String relationshipName) {
49                 super(document, documentID, cpds, tableName);
50
51                 LayoutItem_Portal portal = getPortal(relationshipName);
52                 if (portal == null) {
53                         Log.error(documentID, tableName, "Couldn't find LayoutItem_Portal \"" + relationshipName + "\" in table \""
54                                         + tableName + "\". " + "Cannot retrive data for the related list.");
55                         return;
56                 }
57
58                 parentTable = tableName;
59                 // Reassign the tableName variable to table that is being used for the related list. This needs to be set before
60                 // getFieldsToShowForSQLQuery().
61                 this.tableName = portal.get_table_used("" /* parent table - not relevant */);
62
63                 // Convert the libglom LayoutGroup object into a LayoutFieldVector suitable for SQL queries.
64                 LayoutGroupVector tempLayoutGroupVec = new LayoutGroupVector();
65                 tempLayoutGroupVec.add(portal);
66                 fieldsToGet = getFieldsToShowForSQLQuery(tempLayoutGroupVec);
67
68                 /*
69                  * The code from the rest of this method was ported from Glom: Base_DB::set_found_set_where_clause_for_portal()
70                  */
71                 Relationship relationship = portal.get_relationship();
72
73                 // Notice that, in the case that this is a portal to doubly-related records,
74                 // The WHERE clause mentions the first-related table (though by the alias defined in extra_join)
75                 // and we add an extra JOIN to mention the second-related table.
76
77                 whereClauseToTableName = relationship.get_to_table();
78                 whereClauseToKeyField = getFieldInTable(relationship.get_to_field(), relationship.get_to_table());
79
80                 Relationship relationshipRelated = portal.get_related_relationship();
81                 if (relationshipRelated != null) {
82                         Log.error(documentID, tableName, "The related relationship " + relationshipRelated.get_name()
83                                         + " is not empty but the related relationship code has not been implemented yet.");
84
85                         // FIXME port this Glom code to Java
86                         // @formatter:off
87                         /* 
88                     //Add the extra JOIN:
89                     sharedptr<UsesRelationship> uses_rel_temp = sharedptr<UsesRelationship>::create();
90                     uses_rel_temp->set_relationship(relationship);
91                     found_set.m_extra_join = relationship;
92
93                     //Adjust the WHERE clause appropriately for the extra JOIN:
94                     whereClauseToTableName = uses_rel_temp->get_sql_join_alias_name();
95
96                     const Glib::ustring to_field_name = uses_rel_temp->get_to_field_used();
97                     where_clause_to_key_field = get_fields_for_table_one_field(relationship->get_to_table(), to_field_name);
98                     std::cout << "extra_join=" << found_set.m_extra_join << std::endl;
99                     std::cout << "extra_join where_clause_to_key_field=" << where_clause_to_key_field->get_name() << std::endl;
100                     */
101                     // @formatter:on
102                 }
103
104                 // set portal field
105                 this.portal = portal;
106
107         }
108
109         public ArrayList<DataItem[]> getData(int start, int length, String foreignKeyValue, boolean useSortClause,
110                         int sortColumnIndex, boolean isAscending) {
111
112                 if (tableName == null || foreignKeyValue == null || foreignKeyValue.isEmpty()) {
113                         return null;
114                 }
115
116                 // Set the foreignKeyValue
117                 this.foreignKeyValue = foreignKeyValue;
118
119                 return getListData(start, length, useSortClause, sortColumnIndex, isAscending);
120         }
121
122         /*
123          * (non-Javadoc)
124          * 
125          * @see org.glom.web.server.ListDBAccess#getExpectedResultSize()
126          */
127         public int getExpectedResultSize(String foreignKeyValue) {
128
129                 // Set the foreignKeyValue
130                 this.foreignKeyValue = foreignKeyValue;
131
132                 if (fieldsToGet == null || fieldsToGet.size() <= 0 || this.foreignKeyValue == null)
133                         return -1;
134
135                 return getResultSizeOfSQLQuery();
136         }
137
138         /*
139          * (non-Javadoc)
140          * 
141          * @see org.glom.web.server.ListDBAccess#getSelectQuery(org.glom.libglom.LayoutFieldVector,
142          * org.glom.libglom.SortClause)
143          */
144         @Override
145         protected String getSelectQuery(SortClause sortClause) {
146
147                 if (portal == null) {
148                         Log.error(documentID, parentTable,
149                                         "The Portal has not been found. Cannot build query for the related list.");
150                         return "";
151                 }
152
153                 if (foreignKeyValue == null || foreignKeyValue.isEmpty()) {
154                         Log.error(documentID, parentTable,
155                                         "The value for the foreign key has not been set. Cannot build query for the related list.");
156                         return "";
157                 }
158
159                 return Glom.build_sql_select_with_where_clause(tableName, fieldsToGet, whereClauseToTableName,
160                                 whereClauseToKeyField, foreignKeyValue, null, sortClause);
161
162         }
163
164         private Field getFieldInTable(String fieldName, String tableName) {
165
166                 if (tableName.isEmpty() || fieldName.isEmpty())
167                         return null;
168
169                 FieldVector fields = document.get_table_fields(tableName);
170                 for (int i = 0; i < fields.size(); i++) {
171                         Field field = fields.get(i);
172                         if (fieldName.equals(field.get_name())) {
173                                 return field;
174                         }
175                 }
176
177                 return null;
178         }
179
180         /*
181          * (non-Javadoc)
182          * 
183          * @see org.glom.web.server.ListDBAccess#getCountQuery()
184          */
185         @Override
186         protected String getCountQuery() {
187                 if (portal == null) {
188                         Log.error(documentID, parentTable,
189                                         "The Portal has not been found. Cannot build query for the related list.");
190                         return "";
191                 }
192
193                 if (foreignKeyValue == null || foreignKeyValue.isEmpty()) {
194                         Log.error(documentID, parentTable,
195                                         "The value for the foreign key has not been set. Cannot build query for the related list.");
196                         return "";
197                 }
198
199                 return Glom.build_sql_select_count_with_where_clause(tableName, fieldsToGet, whereClauseToTableName,
200                                 whereClauseToKeyField, foreignKeyValue);
201         }
202
203 }