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;
23 import java.sql.ResultSet;
24 import java.sql.SQLException;
26 import java.text.DateFormat;
27 import java.util.ArrayList;
28 import java.util.Locale;
30 import org.glom.libglom.Document;
31 import org.glom.libglom.Field;
32 import org.glom.libglom.FieldVector;
33 import org.glom.libglom.LayoutFieldVector;
34 import org.glom.libglom.LayoutGroupVector;
35 import org.glom.libglom.LayoutItem;
36 import org.glom.libglom.LayoutItemVector;
37 import org.glom.libglom.LayoutItem_Field;
38 import org.glom.libglom.LayoutItem_Portal;
39 import org.glom.web.server.Log;
40 import org.glom.web.server.Utils;
41 import org.glom.web.shared.DataItem;
43 import com.mchange.v2.c3p0.ComboPooledDataSource;
46 * @author Ben Konrath <ben@bagu.org>
49 abstract class DBAccess {
50 protected Document document;
51 protected String documentID;
52 protected String tableName;
53 protected ComboPooledDataSource cpds;
55 protected DBAccess(Document document, String documentID, ComboPooledDataSource cpds, String tableName) {
56 this.document = document;
57 this.documentID = documentID;
59 this.tableName = tableName;
63 * Converts data from a ResultSet to an ArrayList of DataItem array suitable for sending back to the client.
65 final protected ArrayList<DataItem[]> convertResultSetToDTO(int length, LayoutFieldVector layoutFields, ResultSet rs)
68 // get the data we've been asked for
70 ArrayList<DataItem[]> rowsList = new ArrayList<DataItem[]>();
71 while (rs.next() && rowCount <= length) {
72 int layoutFieldsSize = Utils.safeLongToInt(layoutFields.size());
73 DataItem[] rowArray = new DataItem[layoutFieldsSize];
74 for (int i = 0; i < layoutFieldsSize; i++) {
75 // make a new DataItem to set the text and colours
76 rowArray[i] = new DataItem();
78 // Convert the field value to a string based on the glom type. We're doing the formatting on the
79 // server side for now but it might be useful to move this to the client side.
80 LayoutItem_Field field = layoutFields.get(i);
81 switch (field.get_glom_type()) {
83 String text = rs.getString(i + 1);
84 rowArray[i].setText(text != null ? text : "");
87 rowArray[i].setBoolean(rs.getBoolean(i + 1));
90 rowArray[i].setNumber(rs.getDouble(i + 1));
93 Date date = rs.getDate(i + 1);
95 DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.ROOT);
96 rowArray[i].setText(dateFormat.format(date));
98 rowArray[i].setText("");
102 Time time = rs.getTime(i + 1);
104 DateFormat timeFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM, Locale.ROOT);
105 rowArray[i].setText(timeFormat.format(time));
107 rowArray[i].setText("");
111 byte[] image = rs.getBytes(i + 1);
113 // TODO implement field TYPE_IMAGE
114 rowArray[i].setText("Image (FIXME)");
116 rowArray[i].setText("");
121 Log.warn(documentID, tableName, "Invalid LayoutItem Field type. Using empty string for value.");
122 rowArray[i].setText("");
127 // add the row of DataItems to the ArrayList we're going to return and update the row count
128 rowsList.add(rowArray);
136 * Gets a LayoutFieldVector to use when generating an SQL query.
138 protected LayoutFieldVector getFieldsToShowForSQLQuery(LayoutGroupVector layoutGroupVec) {
139 LayoutFieldVector layoutFieldVector = new LayoutFieldVector();
141 // We will show the fields that the document says we should:
142 for (int i = 0; i < layoutGroupVec.size(); i++) {
143 org.glom.libglom.LayoutGroup layoutGroup = layoutGroupVec.get(i);
145 // satisfy the precondition of getDetailsLayoutGroup(String tableName, org.glom.libglom.LayoutGroup
146 // libglomLayoutGroup)
147 if (layoutGroup == null)
151 ArrayList<LayoutItem_Field> layoutItemFields = getFieldsToShowForSQLQueryAddGroup(layoutGroup);
152 for (LayoutItem_Field layoutItem_Field : layoutItemFields) {
153 layoutFieldVector.add(layoutItem_Field);
156 return layoutFieldVector;
160 * Gets an ArrayList of LayoutItem_Field objects to use when generating an SQL query.
162 * @precondition libglomLayoutGroup must not be null
164 private ArrayList<LayoutItem_Field> getFieldsToShowForSQLQueryAddGroup(
165 org.glom.libglom.LayoutGroup libglomLayoutGroup) {
167 ArrayList<LayoutItem_Field> layoutItemFields = new ArrayList<LayoutItem_Field>();
168 LayoutItemVector items = libglomLayoutGroup.get_items();
169 int numItems = Utils.safeLongToInt(items.size());
170 for (int i = 0; i < numItems; i++) {
171 LayoutItem layoutItem = items.get(i);
173 LayoutItem_Field layoutItemField = LayoutItem_Field.cast_dynamic(layoutItem);
174 if (layoutItemField != null) {
175 // the layoutItem is a LayoutItem_Field
177 if (layoutItemField.get_has_relationship_name()) {
178 // layoutItemField is a field in a related table
179 fields = document.get_table_fields(layoutItemField.get_table_used(tableName));
181 // layoutItemField is a field in this table
182 fields = document.get_table_fields(tableName);
185 // set the layoutItemFeild with details from its Field in the document and
186 // add it to the list to be returned
187 for (int j = 0; j < fields.size(); j++) {
188 // check the names to see if they're the same
189 // this works because we're using the field list from the related table if necessary
190 if (layoutItemField.get_name().equals(fields.get(j).get_name())) {
191 Field field = fields.get(j);
193 layoutItemField.set_full_field_details(field);
194 layoutItemFields.add(layoutItemField);
196 Log.warn(document.get_database_title(), tableName,
197 "LayoutItem_Field " + layoutItemField.get_layout_display_name()
198 + " not found in document field list.");
205 // the layoutItem is not a LayoutItem_Field
206 org.glom.libglom.LayoutGroup subLayoutGroup = org.glom.libglom.LayoutGroup.cast_dynamic(layoutItem);
207 if (subLayoutGroup != null) {
208 // the layoutItem is a LayoutGroup
209 LayoutItem_Portal layoutItemPortal = LayoutItem_Portal.cast_dynamic(layoutItem);
210 if (layoutItemPortal == null) {
211 // The subGroup is not a LayoutItem_Portal.
212 // We're ignoring portals because they are filled by means of a separate SQL query.
213 layoutItemFields.addAll(getFieldsToShowForSQLQueryAddGroup(subLayoutGroup));
218 return layoutItemFields;
222 * Gets the primary key Field for this table.
224 * @return primary key Field
226 protected Field getPrimaryKeyField() {
227 Field primaryKey = null;
228 FieldVector fieldsVec = document.get_table_fields(tableName);
229 for (int i = 0; i < Utils.safeLongToInt(fieldsVec.size()); i++) {
230 Field field = fieldsVec.get(i);
231 if (field.get_primary_key()) {
240 * Gets the primary key LayoutItem_Field for this table.
242 * @return primary key LayoutItem_Field
244 protected LayoutItem_Field getPrimaryKeyLayoutItemField() {
245 Field primaryKey = getPrimaryKeyField();
247 LayoutItem_Field libglomLayoutItemField = new LayoutItem_Field();
249 if (primaryKey != null) {
250 libglomLayoutItemField.set_full_field_details(primaryKey);
252 Log.error(document.get_database_title(), tableName,
253 "A primary key was not found in the FieldVector for this table.");
256 return libglomLayoutItemField;