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