Some import reorganizing by Eclipse
[online-glom:gwt-glom.git] / src / test / java / org / glom / web / shared / libglom / DocumentTest.java
1 /*
2  * Copyright (C) 2009, 2010, 2011 Openismus GmbH
3  *
4  * This file is part of Java-libglom.
5  *
6  * Java-libglom 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  * Java-libglom 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 Java-libglom.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 package org.glom.web.shared.libglom;
21
22 import static org.hamcrest.CoreMatchers.is;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertThat;
25 import static org.junit.Assert.assertTrue;
26
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import org.glom.web.shared.libglom.layout.LayoutGroup;
31 import org.glom.web.shared.libglom.layout.LayoutItem;
32 import org.glom.web.shared.libglom.layout.LayoutItemField;
33 import org.glom.web.shared.libglom.layout.LayoutItemNotebook;
34 import org.glom.web.shared.libglom.layout.LayoutItemPortal;
35 import org.glom.web.shared.libglom.layout.SortClause;
36 import org.glom.web.shared.libglom.layout.reportparts.LayoutItemGroupBy;
37 import org.junit.AfterClass;
38 import org.junit.BeforeClass;
39 import org.junit.Test;
40
41 /**
42  * Simple test to ensure that the generated bindings are working.
43  */
44 public class DocumentTest {
45
46         private static Document document;
47         private static String locale = ""; // This means the original locale.
48         final static String testUriMusicCollection = "src/test/java/org/glom/web/shared/libglom/example_music_collection.glom";
49         final static String testUriFilmManager = "src/test/java/org/glom/web/shared/libglom/example_film_manager.glom";
50
51         @BeforeClass
52         static public void setUp() {
53                 document = new Document();
54                 document.set_file_uri(testUriMusicCollection);
55                 int error = 0;
56                 boolean retval = document.load(error);
57                 assertTrue(retval);
58                 assertEquals(error, 0);
59         }
60
61         @AfterClass
62         static public void tearDown() {
63         }
64
65         @Test
66         public void testDocumentInfo() {
67                 assertThat(document.get_database_title_original(), is("Music Collection"));
68                 assertThat(document.get_default_table(), is("artists"));
69         }
70
71         @Test
72         public void testReadTableNames() {
73                 List<String> tableNames = document.get_table_names();
74                 assertEquals(4, tableNames.size());
75
76                 String tables = tableNames.get(0);
77                 for (int i = 1; i < tableNames.size(); i++) {
78                         tables += ", " + tableNames.get(i);
79                 }
80                 assertThat(tables, is("artists, albums, songs, publishers"));
81         }
82
83         @Test
84         public void testReadTableFieldSizes() {
85
86                 List<Field> fields = document.get_table_fields("albums");
87                 assertEquals(6, fields.size());
88
89                 Field field = fields.get(0);
90                 String titles = field.get_title_or_name(locale);
91                 for (int i = 1; i < fields.size(); i++) {
92                         field = fields.get(i);
93                         titles += ", " + field.get_title_or_name(locale);
94                 }
95
96                 // TODO: The sequence is not important. It's only important that they are all there.
97                 assertThat(titles, is("Publisher ID, Artist ID, Album ID, Name, Year, Comments"));
98
99                 fields = document.get_table_fields("artists");
100                 assertEquals(4, fields.size());
101
102                 field = fields.get(0);
103                 titles = field.get_title_or_name(locale);
104                 for (int i = 1; i < fields.size(); i++) {
105                         field = fields.get(i);
106                         titles += ", " + field.get_title_or_name(locale);
107                 }
108
109                 // TODO: The sequence is not important. It's only important that they are all there.
110                 assertThat(titles, is("Artist ID, Name, Description, Comments"));
111
112                 fields = document.get_table_fields("publishers");
113                 assertEquals(3, fields.size());
114
115                 field = fields.get(0);
116                 titles = field.get_title_or_name(locale);
117                 for (int i = 1; i < fields.size(); i++) {
118                         field = fields.get(i);
119                         titles += ", " + field.get_title_or_name(locale);
120                 }
121
122                 // TODO: The sequence is not important. It's only important that they are all there.
123                 assertThat(titles, is("Name, Publisher ID, Comments"));
124
125                 fields = document.get_table_fields("songs");
126                 assertEquals(4, fields.size());
127
128                 field = fields.get(0);
129                 titles = field.get_title_or_name(locale);
130                 for (int i = 1; i < fields.size(); i++) {
131                         field = fields.get(i);
132                         titles += ", " + field.get_title_or_name(locale);
133                 }
134
135                 // TODO: The sequence is not important. It's only important that they are all there.
136                 assertThat(titles, is("Song ID, Album ID, Name, Comments"));
137         }
138
139         @Test
140         public void testReadLayoutListInfo() {
141                 String[] tables = { "albums", "artists", "publishers", "songs" };
142                 int[] sortClauseSizes = { 0, 1, 1, 1 };
143                 int[] layoutFieldSizes = { 7, 4, 3, 4 };
144
145                 for (int i = 0; i < tables.length; i++) {
146                         List<LayoutGroup> layoutList = document.get_data_layout_groups("list", tables[i]);
147                         assertTrue(!layoutList.isEmpty());
148                         List<LayoutItem> layoutItems = layoutList.get(0).get_items();
149                         List<LayoutItemField> layoutFields = new ArrayList<LayoutItemField>();
150                         SortClause sortClause = new SortClause(); // TODO: Why use a SortClause instead of a List?
151                         int numItems = safeLongToInt(layoutItems.size());
152                         for (int j = 0; j < numItems; j++) {
153                                 LayoutItem item = layoutItems.get(j);
154
155                                 if (item instanceof LayoutItemField) {
156                                         LayoutItemField field = (LayoutItemField) item;
157                                         layoutFields.add(field);
158                                         Field details = field.get_full_field_details();
159                                         if (details != null && details.get_primary_key()) {
160                                                 sortClause.add(new SortClause.SortField(field, true)); // ascending
161                                         }
162                                 }
163                         }
164                         assertEquals(sortClauseSizes[i], sortClause.size());
165                         assertEquals(layoutFieldSizes[i], safeLongToInt(layoutFields.size()));
166                 }
167         }
168
169         /*
170          * This tests if getting values from a NumericFormat object is working. This test was failing with a JVM crash when
171          * using the glom_sharedptr macro with Glom::UsesRelationship and Glom::Formatting.
172          */
173         @Test
174         public void testGetNumericFormat() {
175                 List<String> tableNames = document.get_table_names();
176
177                 for (int i = 0; i < tableNames.size(); i++) {
178                         String table = tableNames.get(i);
179                         List<LayoutGroup> layoutList = document.get_data_layout_groups("list", table);
180                         assertTrue(!layoutList.isEmpty());
181                         List<LayoutItem> layoutItems = layoutList.get(0).get_items();
182                         int numItems = safeLongToInt(layoutItems.size());
183                         for (int j = 0; j < numItems; j++) {
184                                 LayoutItem item = layoutItems.get(j);
185                                 assertTrue(item != null);
186
187                                 if (item instanceof LayoutItemField) {
188                                         final LayoutItemField item_field = (LayoutItemField) item;
189                                         // don't keep a reference to the FeildFormatting object
190                                         NumericFormat numFormat = item_field.get_formatting_used().getNumericFormat();
191                                         assertTrue(numFormat != null);
192
193                                         // get the values
194                                         boolean altForegroundColorForNegatives = numFormat.getUseAltForegroundColorForNegatives();
195                                         String currencySymbol = numFormat.getCurrencySymbol();
196                                         long decimalPlaces = numFormat.getDecimalPlaces();
197                                         boolean decimalPlacesRestricted = numFormat.getDecimalPlacesRestricted();
198                                         boolean useThousandsSepator = numFormat.getUseThousandsSeparator();
199                                         String alternativeColorForNegatives = NumericFormat.getAlternativeColorForNegatives();
200                                         long defaultPrecision = NumericFormat.getDefaultPrecision();
201
202                                         // Simulate a garbage collection
203                                         System.gc();
204                                         System.runFinalization();
205
206                                         // re-get the values and test
207                                         assertEquals(altForegroundColorForNegatives, numFormat.getUseAltForegroundColorForNegatives());
208                                         assertEquals(currencySymbol, numFormat.getCurrencySymbol());
209                                         assertEquals(decimalPlaces, numFormat.getDecimalPlaces());
210                                         assertEquals(decimalPlacesRestricted, numFormat.getDecimalPlacesRestricted());
211                                         assertEquals(useThousandsSepator, numFormat.getUseThousandsSeparator());
212                                         assertEquals(alternativeColorForNegatives, NumericFormat.getAlternativeColorForNegatives());
213                                         assertEquals(defaultPrecision, NumericFormat.getDefaultPrecision());
214
215                                 }
216                         }
217                 }
218         }
219
220         /*
221          * A smoke test for the methods added to LayoutItemField for accessing methods in Glom::UsesRelationship.
222          */
223         @Test
224         public void testUsesRelationshipMethods() {
225                 String table = "albums";
226                 List<LayoutGroup> layoutList = document.get_data_layout_groups("list", table);
227                 List<LayoutItem> layoutItems = layoutList.get(0).get_items();
228
229                 String names = null, hasRelationshipNames = null, tablesUsed = null;
230                 final LayoutItem firstItem = layoutItems.get(0);
231
232                 if (firstItem instanceof LayoutItemField) {
233                         LayoutItemField firstItemField = (LayoutItemField) firstItem;
234                         names = firstItemField.get_name();
235                         hasRelationshipNames = "" + firstItemField.getHasRelationshipName();
236                         tablesUsed = firstItemField.get_table_used(table);
237                 }
238                 int numItems = safeLongToInt(layoutItems.size());
239                 for (int j = 1; j < numItems; j++) {
240                         LayoutItem item = layoutItems.get(j);
241
242                         if (item instanceof LayoutItemField) {
243                                 LayoutItemField itemField = (LayoutItemField) item;
244                                 names += ", " + itemField.get_name();
245                                 hasRelationshipNames += ", " + itemField.getHasRelationshipName();
246                                 tablesUsed += ", " + itemField.get_table_used(table);
247                         }
248                 }
249                 assertEquals("name, year, artist_id, name, publisher_id, name, comments", names);
250                 assertEquals("false, false, false, true, false, true, false", hasRelationshipNames);
251                 assertEquals("albums, albums, albums, artists, albums, publishers, albums", tablesUsed);
252         }
253
254         @Test
255         public void testGetSuitableTableToViewDetails() {
256
257                 // Create a new document for the film manager
258                 Document filmManagerDocument = new Document();
259                 filmManagerDocument.set_file_uri(testUriFilmManager);
260                 int error = 0;
261                 boolean retval = filmManagerDocument.load(error);
262                 assertTrue(retval);
263                 assertEquals(error, 0);
264
265                 // Get the "Scene Cast" related list portal. This relies on specific details of the film manager details
266                 // view layout. I've included safety checks that will fail if the layout changes.
267                 List<LayoutGroup> detailsLayout = filmManagerDocument.get_data_layout_groups("details", "scenes");
268                 assertEquals(3, detailsLayout.size());
269
270                 LayoutGroup layoutGroup = detailsLayout.get(1);
271                 assertEquals("details", layoutGroup.get_name());
272
273                 layoutGroup = detailsLayout.get(2);
274                 assertEquals("details_lower", layoutGroup.get_name());
275
276                 List<LayoutItem> items = layoutGroup.get_items();
277                 assertEquals(2, items.size());
278
279                 LayoutItem notebookItem = items.get(0);
280                 assertEquals("notebook", notebookItem.get_name());
281                 assertTrue(notebookItem instanceof LayoutItemNotebook);
282                 LayoutItemNotebook notebook = (LayoutItemNotebook) notebookItem;
283                 items = notebook.get_items();
284                 assertEquals(7, items.size());
285                 LayoutItem portalItem = items.get(0);
286                 assertTrue(portalItem instanceof LayoutItemPortal);
287                 LayoutItemPortal portal = (LayoutItemPortal) portalItem;
288                 assertTrue(portal != null);
289
290                 assertEquals(portal.getRelationshipNameUsed(), "scene_cast");
291
292                 // call get_suitable_table_to_view_details
293                 final LayoutItemPortal.TableToViewDetails viewDetails = portal
294                                 .get_suitable_table_to_view_details(filmManagerDocument);
295                 assertTrue(viewDetails != null);
296
297                 // Simulate a garbage collection
298                 System.gc();
299                 System.runFinalization();
300
301                 // Check if things are working like we expect
302                 assertEquals("characters", viewDetails.tableName);
303                 assertTrue(viewDetails.usesRelationship != null);
304                 Relationship relationship = viewDetails.usesRelationship.getRelationship();
305                 assertTrue(relationship != null);
306                 assertEquals("cast", relationship.get_name());
307                 assertTrue(viewDetails.usesRelationship.getRelatedRelationship() == null);
308
309         }
310
311         @Test
312         public void testReadReportNames() {
313                 List<String> reportNames = document.get_report_names("albums");
314                 assertEquals(1, reportNames.size()); // TODO: Test something with more reports.
315
316                 String reports = reportNames.get(0);
317                 for (int i = 1; i < reportNames.size(); i++) {
318                         reports += ", " + reportNames.get(i);
319                 }
320                 assertThat(reports, is("albums_by_artist"));
321         }
322
323         @Test
324         public void testReadReportStructure() {
325                 Report report = document.get_report("albums", "albums_by_artist");
326                 assertTrue(report != null);
327                 LayoutGroup layoutGroup = report.get_layout_group();
328                 assertTrue(layoutGroup != null);
329                 List<LayoutItem> layoutItems = layoutGroup.get_items();
330                 final int numItems = safeLongToInt(layoutItems.size());
331                 assertEquals(1, numItems);
332
333                 LayoutItem layoutItem = layoutItems.get(0);
334                 assertTrue(layoutItem != null);
335                 LayoutGroup asGroup = (LayoutGroup) layoutItem;
336                 assertTrue(asGroup != null);
337                 LayoutItemGroupBy groupby = (LayoutItemGroupBy) layoutItem;
338                 assertTrue(groupby != null);
339
340                 assertTrue(groupby.get_has_field_group_by());
341                 LayoutItemField fieldGroupBy = groupby.get_field_group_by();
342                 assertTrue(fieldGroupBy != null);
343                 assertThat(fieldGroupBy.get_name(), is("artist_id"));
344
345                 LayoutGroup groupSecondaries = groupby.get_secondary_fields();
346                 assertTrue(groupSecondaries != null);
347
348                 List<LayoutItem> innerItems = groupby.get_items();
349                 assertTrue(innerItems != null);
350                 final int numInnerItems = safeLongToInt(innerItems.size());
351                 assertEquals(2, numInnerItems);
352
353                 layoutItem = innerItems.get(0);
354                 assertTrue(layoutItem != null);
355                 assertTrue(layoutItem instanceof LayoutItemField);
356                 LayoutItemField field = (LayoutItemField) layoutItem;
357                 assertTrue(field != null);
358                 assertThat(field.get_name(), is("name"));
359                 assertThat(field.get_glom_type(), is(Field.GlomFieldType.TYPE_TEXT));
360
361                 layoutItem = innerItems.get(1);
362                 assertTrue(layoutItem != null);
363                 assertTrue(layoutItem instanceof LayoutItemField);
364                 field = (LayoutItemField) layoutItem;
365                 assertTrue(field != null);
366                 assertThat(field.get_name(), is("year"));
367                 assertThat(field.get_glom_type(), is(Field.GlomFieldType.TYPE_NUMERIC));
368         }
369
370         // Test thread class that runs all the tests.
371         private class TestThread implements Runnable {
372
373                 @Override
374                 public void run() {
375                         for (int i = 0; i < 20; i++) {
376                                 testDocumentInfo();
377                                 testGetNumericFormat();
378                                 testGetSuitableTableToViewDetails();
379                                 testReadLayoutListInfo();
380                                 testReadTableFieldSizes();
381                                 testReadTableNames();
382                                 testUsesRelationshipMethods();
383                         }
384                 }
385         }
386
387         /*
388          * Tests threaded access to java-libglom.
389          */
390         @Test
391         public void testThreadedAccess() throws InterruptedException {
392                 // create the threads
393                 Thread thread1 = new Thread(new TestThread());
394                 Thread thread2 = new Thread(new TestThread());
395                 Thread thread3 = new Thread(new TestThread());
396                 Thread thread4 = new Thread(new TestThread());
397
398                 // start the threads
399                 thread1.start();
400                 thread2.start();
401                 thread3.start();
402                 thread4.start();
403
404                 // wait for the treads to finish
405                 try {
406                         thread1.join();
407                 } catch (InterruptedException e) {
408                         System.out.println("Thread 1 had a problem finishing. " + e);
409                         throw e;
410                 }
411
412                 try {
413                         thread2.join();
414                 } catch (InterruptedException e) {
415                         System.out.println("Thread 2 had a problem finishing. " + e);
416                         throw e;
417                 }
418
419                 try {
420                         thread3.join();
421                 } catch (InterruptedException e) {
422                         System.out.println("Thread 3 had a problem finishing. " + e);
423                         throw e;
424                 }
425
426                 try {
427                         thread4.join();
428                 } catch (InterruptedException e) {
429                         System.out.println("Thread 4 had a problem finishing. " + e);
430                         throw e;
431                 }
432         }
433
434         /*
435          * This method safely converts longs from libglom into ints. This method was taken from stackoverflow:
436          * 
437          * http://stackoverflow.com/questions/1590831/safely-casting-long-to-int-in-java
438          */
439         private static int safeLongToInt(long l) {
440                 if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
441                         throw new IllegalArgumentException(l + " cannot be cast to int without changing its value.");
442                 }
443                 return (int) l;
444         }
445
446 }