Access data from a postgres db rather than the example glom file.
[online-glom:gwt-glom.git] / src / main / java / org / glom / web / server / LibGlomServiceImpl.java
1 package org.glom.web.server;
2
3 import java.beans.PropertyVetoException;
4 import java.sql.Connection;
5 import java.sql.ResultSet;
6 import java.sql.SQLException;
7 import java.sql.Statement;
8 import java.util.ArrayList;
9
10 import org.glom.libglom.Document;
11 import org.glom.libglom.Field;
12 import org.glom.libglom.Glom;
13 import org.glom.libglom.LayoutFieldVector;
14 import org.glom.libglom.LayoutGroupVector;
15 import org.glom.libglom.LayoutItem;
16 import org.glom.libglom.LayoutItemVector;
17 import org.glom.libglom.LayoutItem_Field;
18 import org.glom.libglom.StringVector;
19 import org.glom.web.client.GlomDocument;
20 import org.glom.web.client.GlomTable;
21 import org.glom.web.client.LibGlomService;
22
23 import com.google.gwt.user.server.rpc.RemoteServiceServlet;
24 import com.mchange.v2.c3p0.ComboPooledDataSource;
25 import com.mchange.v2.c3p0.DataSources;
26
27 @SuppressWarnings("serial")
28 public class LibGlomServiceImpl extends RemoteServiceServlet implements LibGlomService {
29         private Document document;
30         ComboPooledDataSource cpds;
31
32         // Called only when the servlet is stopped (the servlet container is stopped or restarted)
33         public LibGlomServiceImpl() {
34                 Glom.libglom_init();
35                 document = new Document();
36                 // TODO hardcoded for now, need to figure out something for this
37                 document.set_file_uri("file:///home/ben/music-collection.glom");
38                 int error = 0;
39                 @SuppressWarnings("unused")
40                 boolean retval = document.load(error);
41                 // TODO handle error condition (also below)
42
43                 cpds = new ComboPooledDataSource();
44                 // load the jdbc driver
45                 try {
46                         cpds.setDriverClass("org.postgresql.Driver");
47                 } catch (PropertyVetoException e) {
48                         // TODO log error, fatal error can't continue, user can be nofified when db access doesn't work
49                         e.printStackTrace();
50                 }
51
52                 cpds.setJdbcUrl("jdbc:postgresql://" + document.get_connection_server() + "/"
53                                 + document.get_connection_database());
54                 // TODO figure out something for db user name and password
55                 cpds.setUser("ben");
56                 cpds.setPassword("ChangeMe"); // of course it's not the password I'm using on my server
57         }
58
59         /* FIXME I think Swig is generating long on 64-bit machines and int on 32-bit machines - need to keep this constant
60          * http://stackoverflow.com/questions /1590831/safely-casting-long-to-int-in-java */
61         public static int safeLongToInt(long l) {
62                 if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
63                         throw new IllegalArgumentException(l + " cannot be cast to int without changing its value.");
64                 }
65                 return (int) l;
66         }
67
68         public GlomDocument getGlomDocument() {
69                 GlomDocument glomDocument = new GlomDocument();
70
71                 // set visible title
72                 glomDocument.setTitle(document.get_database_title());
73
74                 // set array of GlomTables and the default table index
75                 StringVector tableNames = document.get_table_names();
76                 GlomTable[] tables = new GlomTable[safeLongToInt(tableNames.size())];
77                 for (int i = 0; i < tableNames.size(); i++) {
78                         String tableName = tableNames.get(i);
79                         GlomTable glomTable = new GlomTable();
80                         glomTable.setName(tableName);
81                         glomTable.setTitle(document.get_table_title(tableName));
82                         tables[i] = glomTable;
83                         if (tableName.equals(document.get_default_table())) {
84                                 glomDocument.setDefaultTableIndex(i);
85                         }
86                 }
87                 glomDocument.setTables(tables);
88                 return glomDocument;
89
90         }
91
92         public String[] getLayoutListHeaders(String table) {
93                 LayoutGroupVector layoutList = document.get_data_layout_groups("list", table);
94                 LayoutItemVector layoutItems = layoutList.get(0).get_items();
95                 String[] headers = new String[safeLongToInt(layoutItems.size())];
96                 for (int i = 0; i < layoutItems.size(); i++) {
97                         headers[i] = layoutItems.get(i).get_title_or_name();
98                 }
99                 return headers;
100         }
101
102         public ArrayList<String[]> getTableData(int start, int length, String table) {
103                 LayoutGroupVector layoutList = document.get_data_layout_groups("list", table);
104                 LayoutItemVector layoutItems = layoutList.get(0).get_items();
105
106                 LayoutFieldVector layoutFields = new LayoutFieldVector();
107                 for (int i = 0; i < layoutItems.size(); i++) {
108                         LayoutItem item = layoutItems.get(i);
109                         LayoutItem_Field field = LayoutItem_Field.cast_dynamic(item);
110                         if (field != null) {
111                                 layoutFields.add(field);
112                                 Field details = field.get_full_field_details();
113                                 if (details != null && details.get_primary_key()) {
114                                         // TODO implement this for sort order, will need to sort out swig support for std::list in Java
115                                         // C++ code to port to Java:
116                                         // sort_clause.push_back(Glom::type_pair_sort_field(field, true));
117                                 }
118                         }
119                 }
120
121                 ArrayList<String[]> rowsList = new ArrayList<String[]>();
122                 try {
123                         Connection conn = cpds.getConnection();
124                         Statement st = conn.createStatement();
125
126                         String query = Glom.build_sql_select_simple(table, layoutFields);
127                         ResultSet rs = st.executeQuery(query);
128
129                         while (rs.next()) {
130                                 String[] rowArray = new String[safeLongToInt(layoutItems.size())];
131                                 for (int i = 0; i < layoutItems.size(); i++) {
132                                         rowArray[i] = rs.getString(i + 1);
133                                 }
134                                 rowsList.add(rowArray);
135                         }
136
137                         rs.close();
138                         st.close();
139                 } catch (SQLException e) {
140                         // TODO: log error, notify user of problem
141                         e.printStackTrace();
142                 }
143
144                 return rowsList;
145         }
146
147         // Called only when the servlet is stopped (the servlet container is stopped or restarted)
148         public void destroy() {
149                 Glom.libglom_deinit();
150                 try {
151                         DataSources.destroy(cpds);
152                 } catch (SQLException e) {
153                         // TODO log error, don't need to notify user because this is a clean up method
154                         e.printStackTrace();
155                 }
156         }
157
158 }