Rename GlomField to DataItem and update associated methods.
[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;
30 import org.glom.libglom.LayoutItemVector;
31 import org.glom.libglom.LayoutItem_Field;
32 import org.glom.libglom.LayoutItem_Portal;
33 import org.glom.libglom.Relationship;
34 import org.glom.libglom.SortClause;
35 import org.glom.web.server.Log;
36 import org.glom.web.shared.DataItem;
37
38 import com.mchange.v2.c3p0.ComboPooledDataSource;
39
40 /**
41  * @author Ben Konrath <ben@bagu.org>
42  * 
43  */
44 public class RelatedListDBAccess extends ListDBAccess {
45         private String foreignKeyValue = null;
46         private LayoutItem_Portal portal = null;
47         private String parentTable = null;
48         private String whereClauseToTableName = null;
49         private Field whereClauseToKeyField = null;
50
51         public RelatedListDBAccess(Document document, String documentID, ComboPooledDataSource cpds, String tableName,
52                         String relationshipName) {
53                 super(document, documentID, cpds, tableName);
54
55                 // find the LayoutItem_Portal for the related list name
56                 LayoutGroupVector layoutGroupVec = document.get_data_layout_groups("details", tableName);
57                 // LayoutItem_Portal portal = null;
58                 for (int i = 0; i < layoutGroupVec.size(); i++) {
59                         org.glom.libglom.LayoutGroup layoutGroup = layoutGroupVec.get(i);
60                         portal = getPortalForRelationship(relationshipName, layoutGroup);
61                         if (portal != null) {
62                                 break;
63                         }
64                 }
65
66                 if (portal == null) {
67                         Log.error(documentID, tableName, "Couldn't find LayoutItem_Portal \"" + relationshipName + "\" in table \""
68                                         + tableName + "\". " + "Cannot retrive data for the related list.");
69                         return;
70                 }
71
72                 parentTable = tableName;
73                 // Reassign the tableName variable to table that is being used for the related list. This needs to be set before
74                 // getFieldsToShowForSQLQuery().
75                 this.tableName = portal.get_table_used("" /* parent table - not relevant */);
76
77                 // Convert the libglom LayoutGroup object into a LayoutFieldVector suitable for SQL queries.
78                 LayoutGroupVector tempLayoutGroupVec = new LayoutGroupVector();
79                 tempLayoutGroupVec.add(portal);
80                 fieldsToGet = getFieldsToShowForSQLQuery(tempLayoutGroupVec);
81
82                 /*
83                  * The code from the rest of this method was ported from Glom: Base_DB::set_found_set_where_clause_for_portal()
84                  */
85                 Relationship relationship = portal.get_relationship();
86
87                 // Notice that, in the case that this is a portal to doubly-related records,
88                 // The WHERE clause mentions the first-related table (though by the alias defined in extra_join)
89                 // and we add an extra JOIN to mention the second-related table.
90
91                 whereClauseToTableName = relationship.get_to_table();
92                 whereClauseToKeyField = getFieldInTable(relationship.get_to_field(), relationship.get_to_table());
93
94                 Relationship relationshipRelated = portal.get_related_relationship();
95                 if (relationshipRelated != null) {
96                         // FIXME port this Glom code to Java
97                         // @formatter:off
98                         /* 
99                     //Add the extra JOIN:
100                     sharedptr<UsesRelationship> uses_rel_temp = sharedptr<UsesRelationship>::create();
101                     uses_rel_temp->set_relationship(relationship);
102                     found_set.m_extra_join = relationship;
103
104                     //Adjust the WHERE clause appropriately for the extra JOIN:
105                     whereClauseToTableName = uses_rel_temp->get_sql_join_alias_name();
106
107                     const Glib::ustring to_field_name = uses_rel_temp->get_to_field_used();
108                     where_clause_to_key_field = get_fields_for_table_one_field(relationship->get_to_table(), to_field_name);
109                     std::cout << "extra_join=" << found_set.m_extra_join << std::endl;
110                     std::cout << "extra_join where_clause_to_key_field=" << where_clause_to_key_field->get_name() << std::endl;
111                     */
112                     // @formatter:on
113                 }
114
115         }
116
117         public ArrayList<DataItem[]> getData(int start, int length, String foreignKeyValue, boolean useSortClause,
118                         int sortColumnIndex, boolean isAscending) {
119
120                 if (tableName == null || foreignKeyValue == null || foreignKeyValue.isEmpty()) {
121                         return null;
122                 }
123
124                 // Set the foreignKeyValue
125                 this.foreignKeyValue = foreignKeyValue;
126
127                 return getListData(start, length, useSortClause, sortColumnIndex, isAscending);
128         }
129
130         private LayoutItem_Portal getPortalForRelationship(String relationshipName, org.glom.libglom.LayoutGroup layoutGroup) {
131
132                 if (relationshipName == null)
133                         return null;
134
135                 LayoutItemVector items = layoutGroup.get_items();
136                 for (int i = 0; i < items.size(); i++) {
137                         LayoutItem layoutItem = items.get(i);
138
139                         LayoutItem_Field layoutItemField = LayoutItem_Field.cast_dynamic(layoutItem);
140                         if (layoutItemField != null) {
141                                 // the layoutItem is a LayoutItem_Field
142                                 continue;
143
144                         } else {
145                                 // the layoutItem is not a LayoutItem_Field
146                                 org.glom.libglom.LayoutGroup subLayoutGroup = org.glom.libglom.LayoutGroup.cast_dynamic(layoutItem);
147                                 if (subLayoutGroup != null) {
148                                         // the layoutItem is a LayoutGroup
149                                         LayoutItem_Portal layoutItemPortal = LayoutItem_Portal.cast_dynamic(layoutItem);
150                                         if (layoutItemPortal != null) {
151                                                 // The subGroup is a LayoutItem_Protal
152                                                 if (relationshipName.equals(layoutItemPortal.get_relationship_name_used())) {
153                                                         // yey, we found it!
154                                                         return layoutItemPortal;
155                                                 }
156                                         } else {
157                                                 // The subGroup is not a LayoutItem_Portal.
158                                                 LayoutItem_Portal retval = getPortalForRelationship(relationshipName, subLayoutGroup);
159                                                 if (retval != null) {
160                                                         return retval;
161                                                 }
162                                         }
163                                 }
164                         }
165                 }
166
167                 // the LayoutItem_Portal with relationshipName was not found
168                 return null;
169         }
170
171         /*
172          * (non-Javadoc)
173          * 
174          * @see org.glom.web.server.ListDBAccess#getExpectedResultSize()
175          */
176         public int getExpectedResultSize(String foreignKeyValue) {
177
178                 // Set the foreignKeyValue
179                 this.foreignKeyValue = foreignKeyValue;
180
181                 if (fieldsToGet == null || fieldsToGet.size() <= 0 || this.foreignKeyValue == null)
182                         return -1;
183
184                 return getResultSizeOfSQLQuery();
185         }
186
187         /*
188          * (non-Javadoc)
189          * 
190          * @see org.glom.web.server.ListDBAccess#getSelectQuery(org.glom.libglom.LayoutFieldVector,
191          * org.glom.libglom.SortClause)
192          */
193         @Override
194         protected String getSelectQuery(SortClause sortClause) {
195
196                 if (portal == null) {
197                         Log.error(documentID, parentTable,
198                                         "The Portal has not been found. Cannot build query for the related list.");
199                         return "";
200                 }
201
202                 if (foreignKeyValue == null || foreignKeyValue.isEmpty()) {
203                         Log.error(documentID, parentTable,
204                                         "The value for the foreign key has not been set. Cannot build query for the related list.");
205                         return "";
206                 }
207
208                 return Glom.build_sql_select_with_where_clause(tableName, fieldsToGet, whereClauseToTableName,
209                                 whereClauseToKeyField, foreignKeyValue, null, sortClause);
210
211         }
212
213         private Field getFieldInTable(String fieldName, String tableName) {
214
215                 if (tableName.isEmpty() || fieldName.isEmpty())
216                         return null;
217
218                 FieldVector fields = document.get_table_fields(tableName);
219                 for (int i = 0; i < fields.size(); i++) {
220                         Field field = fields.get(i);
221                         if (fieldName.equals(field.get_name())) {
222                                 return field;
223                         }
224                 }
225
226                 return null;
227         }
228
229         /*
230          * (non-Javadoc)
231          * 
232          * @see org.glom.web.server.ListDBAccess#getCountQuery()
233          */
234         @Override
235         protected String getCountQuery() {
236                 if (portal == null) {
237                         Log.error(documentID, parentTable,
238                                         "The Portal has not been found. Cannot build query for the related list.");
239                         return "";
240                 }
241
242                 if (foreignKeyValue == null || foreignKeyValue.isEmpty()) {
243                         Log.error(documentID, parentTable,
244                                         "The value for the foreign key has not been set. Cannot build query for the related list.");
245                         return "";
246                 }
247
248                 return Glom.build_sql_select_count_with_where_clause(tableName, fieldsToGet, whereClauseToTableName,
249                                 whereClauseToKeyField, foreignKeyValue);
250         }
251
252         /*
253          * (non-Javadoc)
254          * 
255          * @see org.glom.web.server.ListDBAccess#getExpectedResultSize()
256          */
257         @Override
258         public int getExpectedResultSize() {
259                 // don't know what the expected size will be without the foreign key
260                 return -1;
261         }
262
263 }