Document: Add and use public constants for layout names.
[online-glom:gwt-glom.git] / src / main / java / org / glom / web / server / database / DetailsDBAccess.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.sql.ResultSet;
24 import java.sql.SQLException;
25 import java.sql.Statement;
26 import java.util.ArrayList;
27 import java.util.List;
28
29 import org.glom.web.server.Log;
30 import org.glom.web.server.SqlUtils;
31 import org.glom.web.server.libglom.Document;
32 import org.glom.web.shared.DataItem;
33 import org.glom.web.shared.TypedDataItem;
34 import org.glom.web.shared.libglom.Field;
35 import org.glom.web.shared.libglom.layout.LayoutItemField;
36
37 import com.mchange.v2.c3p0.ComboPooledDataSource;
38
39 /**
40  *
41  */
42 public class DetailsDBAccess extends DBAccess {
43
44         public DetailsDBAccess(final Document document, final String documentID, final ComboPooledDataSource cpds,
45                         final String tableName) {
46                 super(document, documentID, cpds, tableName);
47                 this.tableName = tableName;
48         }
49
50         public DataItem[] getData(final TypedDataItem primaryKeyValue) {
51
52                 final List<LayoutItemField> fieldsToGet = getFieldsToShowForSQLQuery(document.getDataLayoutGroups(Document.LAYOUT_NAME_DETAILS,
53                                 tableName));
54
55                 if (fieldsToGet == null || fieldsToGet.size() <= 0) {
56                         Log.warn(documentID, tableName, "Didn't find any fields to show. Returning null.");
57                         return null;
58                 }
59
60                 final Field primaryKey = document.getTablePrimaryKeyField(tableName);
61
62                 if (primaryKey == null) {
63                         Log.error(documentID, tableName, "Couldn't find primary key in table. Returning null.");
64                         return null;
65                 }
66
67                 ArrayList<DataItem[]> rowsList = new ArrayList<DataItem[]>();
68                 Connection conn = null;
69                 Statement st = null;
70                 ResultSet rs = null;
71                 try {
72                         // Setup the JDBC driver and get the query.
73                         conn = cpds.getConnection();
74                         st = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
75
76                         if (primaryKeyValue != null) {
77
78                                 final String query = SqlUtils
79                                                 .buildSqlSelectWithKey(tableName, fieldsToGet, primaryKey, primaryKeyValue);
80
81                                 rs = st.executeQuery(query);
82
83                                 // get the results from the ResultSet
84                                 // using 2 as a length parameter so we can log a warning if appropriate
85                                 rowsList = convertResultSetToDTO(2, fieldsToGet, primaryKeyValue, rs);
86                         }
87
88                 } catch (final SQLException e) {
89                         Log.error(documentID, tableName, "Error executing database query.", e);
90                         // TODO: somehow notify user of problem
91                         return null;
92                 } finally {
93                         // cleanup everything that has been used
94                         try {
95                                 if (rs != null) {
96                                         rs.close();
97                                 }
98                                 if (st != null) {
99                                         st.close();
100                                 }
101                                 if (conn != null) {
102                                         conn.close();
103                                 }
104                         } catch (final Exception e) {
105                                 Log.error(documentID, tableName,
106                                                 "Error closing database resources. Subsequent database queries may not work.", e);
107                         }
108                 }
109
110                 if (rowsList.size() == 0) {
111                         Log.error(documentID, tableName, "The query returned an empty ResultSet. Returning null.");
112                         return null;
113                 } else if (rowsList.size() > 1 && (primaryKeyValue != null)) {
114                         // Only log a warning if the result size is greater than 1 and the gdaPrimaryKeyValue is not null. When
115                         // gdaPrimaryKeyValue.is_null() is true, the default query for the details view is being executed so we
116                         // expect a result set that is larger than one.
117                         Log.warn(documentID, tableName,
118                                         "The query did not return the expected unique result. Returning the first result in the set.");
119                 }
120
121                 return rowsList.get(0);
122         }
123 }