Some import reorganizing by Eclipse
[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.sql.Connection;
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import org.apache.commons.lang3.StringUtils;
27 import org.glom.web.server.Log;
28 import org.glom.web.server.SqlUtils;
29 import org.glom.web.shared.DataItem;
30 import org.glom.web.shared.TypedDataItem;
31 import org.glom.web.shared.libglom.Document;
32 import org.glom.web.shared.libglom.Field;
33 import org.glom.web.shared.libglom.Relationship;
34 import org.glom.web.shared.libglom.layout.LayoutGroup;
35 import org.glom.web.shared.libglom.layout.LayoutItemPortal;
36 import org.glom.web.shared.libglom.layout.SortClause;
37 import org.jooq.Condition;
38
39 import com.mchange.v2.c3p0.ComboPooledDataSource;
40
41 /**
42  *
43  */
44 public class RelatedListDBAccess extends ListDBAccess {
45         private TypedDataItem foreignKeyValue = null;
46         private LayoutItemPortal portal = null;
47         private String parentTable = null;
48         private String whereClauseToTableName = null;
49         private Field whereClauseToKeyField = null;
50
51         public RelatedListDBAccess(final Document document, final String documentID, final ComboPooledDataSource cpds,
52                         final String tableName, final String relationshipName) {
53                 super(document, documentID, cpds, tableName);
54
55                 final LayoutItemPortal portal = getPortal(relationshipName);
56                 if (portal == null) {
57                         Log.error(documentID, tableName, "Couldn't find LayoutItem_Portal \"" + relationshipName + "\" in table \""
58                                         + tableName + "\". " + "Cannot retrive data for the related list.");
59                         return;
60                 }
61
62                 parentTable = tableName;
63                 // Reassign the tableName variable to table that is being used for the related list. This needs to be set before
64                 // getFieldsToShowForSQLQuery().
65                 this.tableName = portal.get_table_used("" /* parent table - not relevant */);
66
67                 // Convert the libglom LayoutGroup object into a List<LayoutItem_Field> suitable for SQL queries.
68                 final List<LayoutGroup> tempLayoutGroupVec = new ArrayList<LayoutGroup>();
69                 tempLayoutGroupVec.add(portal);
70                 fieldsToGet = getFieldsToShowForSQLQuery(tempLayoutGroupVec);
71
72                 /*
73                  * The code from the rest of this method was inspired by code from Glom:
74                  * Base_DB::set_found_set_where_clause_for_portal()
75                  */
76                 final Relationship relationship = portal.getRelationship();
77
78                 // Notice that, in the case that this is a portal to doubly-related records,
79                 // The WHERE clause mentions the first-related table (though by the alias defined in extra_join)
80                 // and we add an extra JOIN to mention the second-related table.
81
82                 whereClauseToTableName = relationship.get_to_table();
83                 whereClauseToKeyField = getFieldInTable(relationship.get_to_field(), whereClauseToTableName);
84
85                 // Add primary key
86                 fieldsToGet.add(getPrimaryKeyLayoutItemField(this.tableName));
87
88                 final Relationship relationshipRelated = portal.getRelatedRelationship();
89                 if (relationshipRelated != null) {
90                         Log.error(documentID, tableName, "The related relationship " + relationshipRelated.get_name()
91                                         + " is not empty but the related relationship code has not been implemented yet.");
92
93                         // FIXME port this Glom code to Java
94                         // @formatter:off
95                         /*
96                     //Add the extra JOIN:
97                     sharedptr<UsesRelationship> uses_rel_temp = sharedptr<UsesRelationship>::create();
98                     uses_rel_temp->set_relationship(relationship);
99                     found_set.m_extra_join = relationship;
100
101                     //Adjust the WHERE clause appropriately for the extra JOIN:
102                     whereClauseToTableName = uses_rel_temp->get_sql_join_alias_name();
103
104                     const Glib::ustring to_field_name = uses_rel_temp->get_to_field_used();
105                     where_clause_to_key_field = get_fields_for_table_one_field(relationship->get_to_table(), to_field_name);
106                     std::cout << "extra_join=" << found_set.m_extra_join << std::endl;
107                     std::cout << "extra_join where_clause_to_key_field=" << where_clause_to_key_field->get_name() << std::endl;
108                          */
109                         // @formatter:on
110                 }
111
112                 // set portal field
113                 this.portal = portal;
114
115         }
116
117         public ArrayList<DataItem[]> getData(final int start, final int length, final TypedDataItem foreignKeyValue,
118                         final boolean useSortClause, final int sortColumnIndex, final 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("" /* quickFind */, start, length, useSortClause, sortColumnIndex, isAscending);
128         }
129
130         /*
131          * (non-Javadoc)
132          * 
133          * @see org.glom.web.server.ListDBAccess#getExpectedResultSize()
134          */
135         public int getExpectedResultSize(final TypedDataItem foreignKeyValue) {
136
137                 // Set the foreignKeyValue
138                 this.foreignKeyValue = foreignKeyValue;
139
140                 if (fieldsToGet == null || fieldsToGet.size() <= 0 || this.foreignKeyValue == null)
141                         return -1;
142
143                 return getResultSizeOfSQLQuery();
144         }
145
146         /*
147          * (non-Javadoc)
148          * 
149          * @see org.glom.web.server.ListDBAccess#getSelectQuery(org.glom.libglom.LayoutFieldVector,
150          * org.glom.libglom.SortClause)
151          */
152         @Override
153         protected String getSelectQuery(final Connection connection, final String quickFind, final SortClause sortClause) {
154                 // TODO: combine this method with getCountQuery() to remove duplicate code
155                 if (portal == null) {
156                         Log.error(documentID, parentTable,
157                                         "The Portal has not been found. Cannot build query for the related list.");
158                         return "";
159                 }
160
161                 if (foreignKeyValue == null || foreignKeyValue.isEmpty()) {
162                         Log.error(documentID, parentTable,
163                                         "The value for the foreign key has not been set. Cannot build query for the related list.");
164                         return "";
165                 }
166
167                 Condition whereClause = null; // Note that we ignore quickFind.
168                 // only attempt to make a where clause if it makes sense to do so
169                 if (!StringUtils.isEmpty(whereClauseToTableName)) {
170                         if (foreignKeyValue != null)
171                                 whereClause = SqlUtils.build_simple_where_expression(whereClauseToTableName, whereClauseToKeyField,
172                                                 foreignKeyValue);
173                 }
174
175                 return SqlUtils.build_sql_select_with_where_clause(connection, tableName, fieldsToGet, whereClause, sortClause);
176
177         }
178
179         private Field getFieldInTable(final String fieldName, final String tableName) {
180
181                 if (StringUtils.isEmpty(tableName))
182                         return null;
183
184                 final List<Field> fields = document.get_table_fields(tableName);
185                 for (int i = 0; i < fields.size(); i++) {
186                         final Field field = fields.get(i);
187                         if (fieldName.equals(field.get_name())) {
188                                 return field;
189                         }
190                 }
191
192                 return null;
193         }
194
195         /*
196          * (non-Javadoc)
197          * 
198          * @see org.glom.web.server.ListDBAccess#getCountQuery()
199          */
200         @Override
201         protected String getCountQuery(final Connection connection) {
202                 // TODO: combine this method with getSelectQuery() to remove duplicate code
203                 if (portal == null) {
204                         Log.error(documentID, parentTable,
205                                         "The Portal has not been found. Cannot build query for the related list.");
206                         return "";
207                 }
208
209                 if (foreignKeyValue == null || foreignKeyValue.isEmpty()) {
210                         Log.error(documentID, parentTable,
211                                         "The value for the foreign key has not been set. Cannot build query for the related list.");
212                         return "";
213                 }
214
215                 Condition whereClause = null;
216                 // only attempt to make a where clause if it makes sense to do so
217                 if (!whereClauseToTableName.isEmpty() && whereClauseToKeyField != null) {
218                         if (foreignKeyValue != null)
219                                 whereClause = SqlUtils.build_simple_where_expression(whereClauseToTableName, whereClauseToKeyField,
220                                                 foreignKeyValue);
221                 }
222
223                 return SqlUtils.build_sql_count_select_with_where_clause(connection, tableName, fieldsToGet, whereClause);
224         }
225
226 }