Replace deprecated DOM.setElementAttribute().
[online-glom:gwt-glom.git] / src / main / java / org / glom / web / server / OnlineGlomServiceImpl.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.sql.Connection;
23 import java.sql.SQLException;
24 import java.util.ArrayList;
25
26 import javax.servlet.ServletException;
27
28 import org.apache.commons.lang3.StringUtils;
29 import org.glom.web.client.OnlineGlomService;
30 import org.glom.web.server.libglom.Document;
31 import org.glom.web.shared.DataItem;
32 import org.glom.web.shared.DetailsLayoutAndData;
33 import org.glom.web.shared.DocumentInfo;
34 import org.glom.web.shared.Documents;
35 import org.glom.web.shared.NavigationRecord;
36 import org.glom.web.shared.Reports;
37 import org.glom.web.shared.TypedDataItem;
38 import org.glom.web.shared.libglom.Report;
39 import org.glom.web.shared.libglom.layout.LayoutGroup;
40 import org.glom.web.shared.libglom.layout.LayoutItemPortal;
41
42 import com.mchange.v2.c3p0.ComboPooledDataSource;
43
44 /**
45  * This is the servlet class for setting up the server side of Online Glom. The client side can call the public methods
46  * in this class via OnlineGlom
47  * 
48  * For instance, it loads all the available documents and provide a list - see (). It then provides
49  * information from each document. For instance, see getListViewLayout().
50  * 
51  * TODO: Watch for changes to the .glom files, to reload new versions and to load newly-added files. TODO: Watch for
52  * changes to the properties (configuration)?
53  */
54 @SuppressWarnings("serial")
55 public class OnlineGlomServiceImpl extends OnlineGlomServlet implements OnlineGlomService {
56
57         
58         /*
59          * This is called when the servlet is stopped or restarted.
60          * 
61          * @see javax.servlet.GenericServlet#destroy()
62          */
63         @Override
64         public void destroy() {
65                 //TODO: This is an arbitrary place to do this,
66                 //because this is shared by all servlets.
67                 //It is even necessary?
68                 final ConfiguredDocumentSet configuredDocumentSet = getConfiguredDocumentSet();
69                 if(configuredDocumentSet != null) {
70                         configuredDocumentSet.forgetDocuments();
71                 }
72         }
73
74         /*
75          * (non-Javadoc)
76          * 
77          * @see org.glom.web.client.OnlineGlomService#getConfigurationErrorMessage()
78          */
79         @Override
80         public String getConfigurationErrorMessage() {
81                 final ConfiguredDocumentSet configuredDocumentSet = getConfiguredDocumentSet();
82                 if(configuredDocumentSet == null) {
83                         Log.error("Could not get the configuredDocumentSet.");
84                         return "";
85                 }       
86                         
87                 final Exception configurationException = configuredDocumentSet.getConfigurationException();
88                 if (configurationException == null) {
89                         return "No configuration errors to report.";
90                 } else if (configurationException.getMessage() == null) {
91                         return configurationException.toString();
92                 } else {
93                         return configurationException.getMessage();
94                 }
95         }
96
97         /*
98          * (non-Javadoc)
99          * 
100          * @see org.glom.web.client.OnlineGlomService#getDetailsData(java.lang.String, java.lang.String, java.lang.String)
101          */
102         @Override
103         public DataItem[] getDetailsData(final String documentID, final String tableName,
104                         final TypedDataItem primaryKeyValue) {
105                 final ComboPooledDataSource authenticatedConnection = getConnection(documentID);
106                 if(authenticatedConnection == null) {
107                         return new DataItem[0];
108                 }
109
110                 // An empty tableName is OK, because that means the default table.
111
112                 final ConfiguredDocument configuredDoc = getDocument(documentID);
113                 if (configuredDoc == null) {
114                         return new DataItem[0];
115                 }
116
117                 return configuredDoc.getDetailsData(authenticatedConnection, tableName, primaryKeyValue);
118         }
119
120         /*
121          * (non-Javadoc)
122          * 
123          * @see org.glom.web.client.OnlineGlomService#getDetailsLayoutAndData(java.lang.String, java.lang.String,
124          * java.lang.String)
125          */
126         @Override
127         public DetailsLayoutAndData getDetailsLayoutAndData(final String documentID, final String tableName,
128                         final TypedDataItem primaryKeyValue, final String localeID) {
129                 final ComboPooledDataSource authenticatedConnection = getConnection(documentID);
130                 if(authenticatedConnection == null) {
131                         return null;
132                 }
133
134                 // An empty tableName is OK, because that means the default table.
135
136                 final ConfiguredDocument configuredDoc = getDocument(documentID);
137                 if (configuredDoc == null) {
138                         return null;
139                 }
140
141                 final DetailsLayoutAndData initalDetailsView = new DetailsLayoutAndData();
142                 initalDetailsView
143                                 .setLayout(configuredDoc.getDetailsLayoutGroup(tableName, StringUtils.defaultString(localeID)));
144                 initalDetailsView.setData(configuredDoc.getDetailsData(authenticatedConnection, tableName, primaryKeyValue));
145
146                 return initalDetailsView;
147         }
148
149         /*
150          * (non-Javadoc)
151          * 
152          * @see org.glom.web.client.OnlineGlomService#getDocumentInfo(java.lang.String)
153          */
154         @Override
155         public DocumentInfo getDocumentInfo(final String documentID, final String localeID) {
156
157                 if (!isAuthenticated(documentID)) {
158                         return new DocumentInfo();
159                 }
160
161                 final ConfiguredDocument configuredDoc = getDocument(documentID);
162
163                 // Avoid dereferencing a null object:
164                 if (configuredDoc == null) {
165                         return new DocumentInfo();
166                 }
167
168                 return configuredDoc.getDocumentInfo(StringUtils.defaultString(localeID));
169         }
170
171         /*
172          * (non-Javadoc)
173          * 
174          * @see org.glom.web.client.OnlineGlomService#getDocuments()
175          */
176         @Override
177         public Documents getDocuments() {
178                 final ConfiguredDocumentSet configuredDocumentSet = getConfiguredDocumentSet();
179                 if(configuredDocumentSet == null) {
180                         Log.error("Could not get the configuredDocumentSet.");
181                         return null;
182                 }
183
184                 return configuredDocumentSet.getDocuments();
185         }
186
187         /*
188          * (non-Javadoc)
189          * 
190          * @see org.glom.web.client.OnlineGlomService#getListViewData(java.lang.String, java.lang.String, int, int, int,
191          * boolean)
192          */
193         @Override
194         public ArrayList<DataItem[]> getListViewData(final String documentID, final String tableName,
195                         final String quickFind, final int start, final int length, final int sortColumnIndex,
196                         final boolean isAscending) {
197                 if (!isAuthenticated(documentID)) {
198                         return new ArrayList<DataItem[]>();
199                 }
200
201                 final ConfiguredDocument configuredDoc = getDocument(documentID);
202                 if (configuredDoc == null) {
203                         return new ArrayList<DataItem[]>();
204                 }
205                 
206                 final ComboPooledDataSource authenticatedConnection = getConnection(documentID);
207                 if(authenticatedConnection == null) {
208                         return new ArrayList<DataItem[]>();
209                 }
210
211                 return configuredDoc.getListViewData(authenticatedConnection, tableName, quickFind, start, length, true, sortColumnIndex, isAscending);
212         }
213
214         /*
215          * (non-Javadoc)
216          * 
217          * @see org.glom.web.client.OnlineGlomService#getListViewLayout(java.lang.String, java.lang.String)
218          */
219         @Override
220         public LayoutGroup getListViewLayout(final String documentID, final String tableName, final String localeID) {
221                 if (!isAuthenticated(documentID)) {
222                         return new LayoutGroup();
223                 }
224
225                 final ConfiguredDocument configuredDoc = getDocument(documentID);
226                 if (configuredDoc == null) {
227                         return new LayoutGroup();
228                 }
229
230                 return configuredDoc.getListViewLayoutGroup(tableName, StringUtils.defaultString(localeID));
231         }
232
233         /*
234          * (non-Javadoc)
235          * 
236          * @see org.glom.web.client.OnlineGlomService#getRelatedListData(java.lang.String, java.lang.String, int, int, int,
237          * boolean)
238          */
239         @Override
240         public ArrayList<DataItem[]> getRelatedListData(final String documentID, final String tableName,
241                         final LayoutItemPortal portal, final TypedDataItem foreignKeyValue, final int start, final int length,
242                         final int sortColumnIndex, final boolean ascending) {
243                 if (!isAuthenticated(documentID)) {
244                         return new ArrayList<DataItem[]>();
245                 }
246
247                 // An empty tableName is OK, because that means the default table.
248
249                 if (portal == null) {
250                         Log.error("getRelatedListData(): portal is null.");
251                         return null;
252                 }
253
254                 final ConfiguredDocument configuredDoc = getDocument(documentID);
255                 if (configuredDoc == null) {
256                         return new ArrayList<DataItem[]>();
257                 }
258                 
259                 final ComboPooledDataSource authenticatedConnection = getConnection(documentID);
260                 if(authenticatedConnection == null) {
261                         return null;
262                 }
263
264                 return configuredDoc.getRelatedListData(authenticatedConnection, tableName, portal, foreignKeyValue, start, length, sortColumnIndex,
265                                 ascending);
266         }
267
268         @Override
269         public int getRelatedListRowCount(final String documentID, final String tableName, final LayoutItemPortal portal,
270                         final TypedDataItem foreignKeyValue) {
271                 if (!isAuthenticated(documentID)) {
272                         return 0;
273                 }
274
275                 // An empty tableName is OK, because that means the default table.
276
277                 if (portal == null) {
278                         Log.error("getRelatedListRowCount(): portal is null");
279                         return 0;
280                 }
281
282                 final ConfiguredDocument configuredDoc = getDocument(documentID);
283                 if (configuredDoc == null) {
284                         return 0;
285                 }
286                 
287                 final ComboPooledDataSource authenticatedConnection = getConnection(documentID);
288                 if(authenticatedConnection == null) {
289                         return 0;
290                 }
291
292                 return configuredDoc.getRelatedListRowCount(authenticatedConnection, tableName, portal, foreignKeyValue);
293         }
294
295         // TODO: Specify the foundset (via a where clause) and maybe a default sort order.
296         /*
297          * (non-Javadoc)
298          * 
299          * @see org.glom.web.client.OnlineGlomService#getReportLayout(java.lang.String, java.lang.String, java.lang.String,
300          * java.lang.String)
301          */
302         @Override
303         public String getReportHTML(final String documentID, final String tableName, final String reportName,
304                         final String quickFind, final String localeID) {
305                 if (!isAuthenticated(documentID)) {
306                         return "";
307                 }
308
309                 final ConfiguredDocument configuredDoc = getDocument(documentID);
310                 if (configuredDoc == null) {
311                         return "";
312                 }
313
314                 final Document glomDocument = configuredDoc.getDocument();
315                 if (glomDocument == null) {
316                         final String errorMessage = "getReportHTML(): getDocument() failed.";
317                         Log.fatal(errorMessage);
318                         // TODO: throw new Exception(errorMessage);
319                         return "";
320                 }
321
322                 final Report report = glomDocument.getReport(tableName, reportName);
323                 if (report == null) {
324                         Log.info(documentID, tableName, "The report layout is not defined for this table:" + reportName);
325                         return "";
326                 }
327                 
328                 final ComboPooledDataSource authenticatedConnection = getConnection(documentID);
329                 if(authenticatedConnection == null) {
330                         return "";
331                 }
332
333                 Connection connection;
334                 try {
335                         connection = authenticatedConnection.getConnection();
336                 } catch (final SQLException e2) {
337                         // TODO Auto-generated catch block
338                         e2.printStackTrace();
339                         return "Connection Failed";
340                 }
341
342                 // TODO: Use quickFind
343                 final ReportGenerator generator = new ReportGenerator(StringUtils.defaultString(localeID));
344                 return generator.generateReport(glomDocument, tableName, report, connection, quickFind);
345         }
346
347         /*
348          * (non-Javadoc)
349          * 
350          * @see org.glom.web.client.OnlineGlomService#getReportsList(java.lang.String, java.lang.String, java.lang.String)
351          */
352         @Override
353         public Reports getReportsList(final String documentID, final String tableName, final String localeID) {
354                 final ConfiguredDocument configuredDoc = getDocument(documentID);
355                 if(configuredDoc != null) {
356                         return configuredDoc.getReports(tableName, localeID);
357                 } else {
358                         return null;
359                 }
360         }
361
362         // TODO: It would be more efficient to get the extra related (or related related) column value along with the other
363         // values,
364         // instead of doing a separate SQL query to get it now for a specific row.
365         /*
366          * (non-Javadoc)
367          * 
368          * @see org.glom.web.client.OnlineGlomService#getSuitableRecordToViewDetails(java.lang.String, java.lang.String,
369          * java.lang.String, java.lang.String)
370          */
371         @Override
372         public NavigationRecord getSuitableRecordToViewDetails(final String documentID, final String tableName,
373                         final LayoutItemPortal portal, final TypedDataItem primaryKeyValue) {
374                 final ComboPooledDataSource authenticatedConnection = getConnection(documentID);
375                 if(authenticatedConnection == null) {
376                         return null;
377                 }
378
379                 // An empty tableName is OK, because that means the default table.
380
381                 if (portal == null) {
382                         Log.error("getSuitableRecordToViewDetails(): portal is null");
383                         return null;
384                 }
385
386                 final ConfiguredDocument configuredDoc = getDocument(documentID);
387                 if (configuredDoc == null) {
388                         return null;
389                 }
390
391                 return configuredDoc.getSuitableRecordToViewDetails(authenticatedConnection, tableName, portal, primaryKeyValue);
392         }
393
394         /*
395          * This is called when the servlet is started or restarted.
396          * 
397          * (non-Javadoc)
398          * 
399          * @see javax.servlet.GenericServlet#init()
400          */
401         @Override
402         public void init() throws ServletException {
403         }
404
405 }