Java tutorial
/* * Copyright (C) 2009, 2010, 2011 Openismus GmbH * * This file is part of gwt-glom * * gwt-glom is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * gwt-glom is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with gwt-glom. If not, see <http://www.gnu.org/licenses/>. */ package org.glom.web.server.libglom; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.*; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.glom.web.shared.DataItem; import org.glom.web.shared.libglom.Field; import org.glom.web.shared.libglom.NumericFormat; import org.glom.web.shared.libglom.Relationship; import org.glom.web.shared.libglom.Report; import org.glom.web.shared.libglom.Translatable; import org.glom.web.shared.libglom.layout.LayoutGroup; import org.glom.web.shared.libglom.layout.LayoutItem; import org.glom.web.shared.libglom.layout.LayoutItemField; import org.glom.web.shared.libglom.layout.LayoutItemNotebook; import org.glom.web.shared.libglom.layout.LayoutItemPortal; import org.glom.web.shared.libglom.layout.LayoutItemText; import org.glom.web.shared.libglom.layout.SortClause; import org.glom.web.shared.libglom.layout.StaticText; import org.glom.web.shared.libglom.layout.TableToViewDetails; import org.glom.web.shared.libglom.layout.reportparts.LayoutItemGroupBy; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; /** * Simple test to ensure that the generated bindings are working. */ public class DocumentTest { private static Document document; private static String defaultLocale = ""; private static String germanLocale = "de"; static String testUriMusicCollection = ""; static String testUriFilmManager = ""; @BeforeClass static public void setUp() { URL url = DocumentTest.class.getResource("example_music_collection.glom"); assertTrue(url != null); testUriMusicCollection = url.toString(); assertTrue(!StringUtils.isEmpty(testUriMusicCollection)); url = DocumentTest.class.getResource("example_film_manager.glom"); assertTrue(url != null); testUriFilmManager = url.toString(); assertTrue(!StringUtils.isEmpty(testUriFilmManager)); document = new Document(); document.setFileURI(testUriMusicCollection); final boolean retval = document.load(); assertTrue(retval); } @AfterClass static public void tearDown() { } @Test public void testDocumentInfo() { assertThat(document.getDatabaseTitleOriginal(), is("Music Collection")); assertThat(document.getDatabaseTitle(defaultLocale), is("Music Collection")); assertThat(document.getDatabaseTitle(germanLocale), is("Musiksammlung")); assertThat(document.getDefaultTable(), is("artists")); } @Test public void testLocales() { final List<String> localeIDs = document.getTranslationAvailableLocales(); assertEquals(11, localeIDs.size()); String tables = localeIDs.get(0); for (int i = 1; i < localeIDs.size(); i++) { tables += ", " + localeIDs.get(i); } assertThat(tables, is("cs, de, el, es, fr, gl, id, lv, pt_BR, sl, en")); } @Test public void testReadTableNames() { final List<String> tableNames = document.getTableNames(); assertEquals(4, tableNames.size()); String tables = tableNames.get(0); for (int i = 1; i < tableNames.size(); i++) { tables += ", " + tableNames.get(i); } assertThat(tables, is("artists, albums, songs, publishers")); } String getTitles(final List<Field> list, final String locale) { String result = ""; for (int i = 0; i < list.size(); i++) { final Translatable item = list.get(i); if (i != 0) { result += ", "; } result += item.getTitleOrName(locale); } return result; } @Test public void testReadTableFieldSizes() { List<Field> fields = document.getTableFields("albums"); assertEquals(6, fields.size()); // TODO: The sequence is not important. It's only important that they are all there. assertThat(getTitles(fields, defaultLocale), is("Publisher ID, Artist ID, Album ID, Name, Year, Comments")); assertThat(getTitles(fields, germanLocale), is("Herausgeber-Kennung, Knstlerkennung, Albenkennung, Name, Jahr, Kommentare")); fields = document.getTableFields("artists"); assertEquals(4, fields.size()); // TODO: The sequence is not important. It's only important that they are all there. assertThat(getTitles(fields, defaultLocale), is("Artist ID, Name, Description, Comments")); assertThat(getTitles(fields, germanLocale), is("Knstlerkennung, Name, Beschreibung, Kommentare")); fields = document.getTableFields("publishers"); assertEquals(3, fields.size()); // TODO: The sequence is not important. It's only important that they are all there. assertThat(getTitles(fields, defaultLocale), is("Name, Publisher ID, Comments")); assertThat(getTitles(fields, germanLocale), is("Name, Herausgeber-Kennung, Kommentare")); fields = document.getTableFields("songs"); assertEquals(4, fields.size()); // TODO: The sequence is not important. It's only important that they are all there. assertThat(getTitles(fields, defaultLocale), is("Song ID, Album ID, Name, Comments")); assertThat(getTitles(fields, germanLocale), is("Lied-Kennung, Albenkennung, Name, Kommentare")); } @Test public void testReadTableExampleRows() { final List<Map<String, DataItem>> exampleRows = document.getExampleRows("albums"); assertFalse(exampleRows.isEmpty()); final Map<String, DataItem> row = exampleRows.get(0); assertFalse(row.isEmpty()); } @Test public void testReadLayoutListInfo() { final String[] tables = { "albums", "artists", "publishers", "songs" }; final int[] sortClauseSizes = { 0, 1, 1, 1 }; final int[] layoutFieldSizes = { 7, 4, 3, 4 }; for (int i = 0; i < tables.length; i++) { final List<LayoutGroup> layoutList = document.getDataLayoutGroups(Document.LAYOUT_NAME_LIST, tables[i]); assertTrue(!layoutList.isEmpty()); final List<LayoutItem> layoutItems = layoutList.get(0).getItems(); final List<LayoutItemField> layoutFields = new ArrayList<LayoutItemField>(); final SortClause sortClause = new SortClause(); // TODO: Why use a SortClause instead of a List? final int numItems = safeLongToInt(layoutItems.size()); for (int j = 0; j < numItems; j++) { final LayoutItem item = layoutItems.get(j); if (item instanceof LayoutItemField) { final LayoutItemField field = (LayoutItemField) item; layoutFields.add(field); final Field details = field.getFullFieldDetails(); if (details != null && details.getPrimaryKey()) { sortClause.add(new SortClause.SortField(field, true)); // ascending } } } assertEquals(sortClauseSizes[i], sortClause.size()); assertEquals(layoutFieldSizes[i], safeLongToInt(layoutFields.size())); } } /* * This tests if getting values from a NumericFormat object is working. This test was failing with a JVM crash when * using the glom_sharedptr macro with Glom::UsesRelationship and Glom::Formatting. */ @Test public void testGetNumericFormat() { final List<String> tableNames = document.getTableNames(); for (int i = 0; i < tableNames.size(); i++) { final String table = tableNames.get(i); final List<LayoutGroup> layoutList = document.getDataLayoutGroups(Document.LAYOUT_NAME_LIST, table); assertTrue(!layoutList.isEmpty()); final LayoutGroup firstgroup = layoutList.get(0); assertTrue(firstgroup != null); final List<LayoutItem> layoutItems = firstgroup.getItems(); final int numItems = safeLongToInt(layoutItems.size()); for (int j = 0; j < numItems; j++) { final LayoutItem item = layoutItems.get(j); assertTrue(item != null); if (item instanceof LayoutItemField) { final LayoutItemField itemField = (LayoutItemField) item; // don't keep a reference to the FeildFormatting object final NumericFormat numFormat = itemField.getFormattingUsed().getNumericFormat(); assertTrue(numFormat != null); // get the values final boolean altForegroundColorForNegatives = numFormat.getUseAltForegroundColorForNegatives(); final String currencySymbol = numFormat.getCurrencySymbol(); final long decimalPlaces = numFormat.getDecimalPlaces(); final boolean decimalPlacesRestricted = numFormat.getDecimalPlacesRestricted(); final boolean useThousandsSepator = numFormat.getUseThousandsSeparator(); final String alternativeColorForNegatives = NumericFormat .getAlternativeColorForNegativesAsHTMLColor(); final long defaultPrecision = NumericFormat.getDefaultPrecision(); // Simulate a garbage collection System.gc(); System.runFinalization(); // re-get the values and test assertEquals(altForegroundColorForNegatives, numFormat.getUseAltForegroundColorForNegatives()); assertEquals(currencySymbol, numFormat.getCurrencySymbol()); assertEquals(decimalPlaces, numFormat.getDecimalPlaces()); assertEquals(decimalPlacesRestricted, numFormat.getDecimalPlacesRestricted()); assertEquals(useThousandsSepator, numFormat.getUseThousandsSeparator()); assertEquals(alternativeColorForNegatives, NumericFormat.getAlternativeColorForNegativesAsHTMLColor()); assertEquals(defaultPrecision, NumericFormat.getDefaultPrecision()); } } } } /* * A smoke test for the methods added to LayoutItemField for accessing methods in Glom::UsesRelationship. */ @Test public void testUsesRelationshipMethods() { final String table = "albums"; final List<LayoutGroup> layoutList = document.getDataLayoutGroups(Document.LAYOUT_NAME_LIST, table); final List<LayoutItem> layoutItems = layoutList.get(0).getItems(); String names = null, hasRelationshipNames = null, tablesUsed = null; final LayoutItem firstItem = layoutItems.get(0); if (firstItem instanceof LayoutItemField) { final LayoutItemField firstItemField = (LayoutItemField) firstItem; names = firstItemField.getName(); hasRelationshipNames = "" + firstItemField.getHasRelationshipName(); tablesUsed = firstItemField.getTableUsed(table); } final int numItems = safeLongToInt(layoutItems.size()); for (int j = 1; j < numItems; j++) { final LayoutItem item = layoutItems.get(j); if (item instanceof LayoutItemField) { final LayoutItemField itemField = (LayoutItemField) item; names += ", " + itemField.getName(); hasRelationshipNames += ", " + itemField.getHasRelationshipName(); tablesUsed += ", " + itemField.getTableUsed(table); } } assertEquals("name, year, artist_id, name, publisher_id, name, comments", names); assertEquals("false, false, false, true, false, true, false", hasRelationshipNames); assertEquals("albums, albums, albums, artists, albums, publishers, albums", tablesUsed); } @Test public void testLayoutItemText() { // Create a new document for the film manager final Document filmManagerDocument = new Document(); filmManagerDocument.setFileURI(testUriFilmManager); final boolean retval = filmManagerDocument.load(); assertTrue(retval); // This relies on specific details of the film manager details // view layout. I've included safety checks that will fail if the layout changes. final List<LayoutGroup> detailsLayout = filmManagerDocument .getDataLayoutGroups(Document.LAYOUT_NAME_DETAILS, "scenes"); assertEquals(3, detailsLayout.size()); LayoutGroup layoutGroup = detailsLayout.get(1); assertEquals(Document.LAYOUT_NAME_DETAILS, layoutGroup.getName()); final List<LayoutItem> items = layoutGroup.getItems(); final LayoutItem item = items.get(1); assertTrue(item instanceof LayoutItemText); LayoutItemText itemText = (LayoutItemText) item; StaticText text = itemText.getText(); assertEquals(text.getTitle(), "The location name will be used if the name is empty."); } @Test public void testGetSuitableTableToViewDetails() { // Create a new document for the film manager final Document filmManagerDocument = new Document(); filmManagerDocument.setFileURI(testUriFilmManager); final boolean retval = filmManagerDocument.load(); assertTrue(retval); // Get the "Scene Cast" related list portal. This relies on specific details of the film manager details // view layout. I've included safety checks that will fail if the layout changes. final List<LayoutGroup> detailsLayout = filmManagerDocument .getDataLayoutGroups(Document.LAYOUT_NAME_DETAILS, "scenes"); assertEquals(3, detailsLayout.size()); LayoutGroup layoutGroup = detailsLayout.get(1); assertEquals(Document.LAYOUT_NAME_DETAILS, layoutGroup.getName()); assertEquals("Details", layoutGroup.getTitle(defaultLocale)); assertEquals("Details", layoutGroup.getTitle(germanLocale)); layoutGroup = detailsLayout.get(2); assertEquals("details_lower", layoutGroup.getName()); List<LayoutItem> items = layoutGroup.getItems(); assertEquals(2, items.size()); final LayoutItem notebookItem = items.get(0); assertEquals("notebook", notebookItem.getName()); assertTrue(notebookItem instanceof LayoutItemNotebook); final LayoutItemNotebook notebook = (LayoutItemNotebook) notebookItem; items = notebook.getItems(); assertEquals(7, items.size()); final LayoutItem portalItem = items.get(0); assertTrue(portalItem instanceof LayoutItemPortal); final LayoutItemPortal portal = (LayoutItemPortal) portalItem; assertTrue(portal != null); assertEquals("scene_cast", portal.getRelationshipNameUsed()); assertEquals("Cast", portal.getTitle(defaultLocale)); assertEquals("Szene Besetzung", portal.getTitle(germanLocale)); // call getSuitableTableToViewDetails final TableToViewDetails viewDetails = filmManagerDocument.getPortalSuitableTableToViewDetails(portal); assertTrue(viewDetails != null); // Simulate a garbage collection System.gc(); System.runFinalization(); // Check if things are working like we expect assertEquals("characters", viewDetails.tableName); assertTrue(viewDetails.usesRelationship != null); final Relationship relationship = viewDetails.usesRelationship.getRelationship(); assertTrue(relationship != null); assertEquals("cast", relationship.getName()); assertTrue(viewDetails.usesRelationship.getRelatedRelationship() == null); } @Test public void testReadReportNames() { final List<String> reportNames = document.getReportNames("albums"); assertEquals(1, reportNames.size()); // TODO: Test something with more reports. String reports = reportNames.get(0); for (int i = 1; i < reportNames.size(); i++) { reports += ", " + reportNames.get(i); } assertThat(reports, is("albums_by_artist")); } @Test public void testReadReportStructure() { final Report report = document.getReport("albums", "albums_by_artist"); assertTrue(report != null); assertThat(report.getTitle(defaultLocale), is("Albums By Artist")); assertThat(report.getTitle(germanLocale), is("Alben nach Knstler")); final LayoutGroup layoutGroup = report.getLayoutGroup(); assertTrue(layoutGroup != null); final List<LayoutItem> layoutItems = layoutGroup.getItems(); final int numItems = safeLongToInt(layoutItems.size()); assertEquals(1, numItems); LayoutItem layoutItem = layoutItems.get(0); assertTrue(layoutItem != null); final LayoutGroup asGroup = (LayoutGroup) layoutItem; assertTrue(asGroup != null); final LayoutItemGroupBy groupby = (LayoutItemGroupBy) layoutItem; assertTrue(groupby != null); assertTrue(groupby.getHasFieldGroupBy()); final LayoutItemField fieldGroupBy = groupby.getFieldGroupBy(); assertTrue(fieldGroupBy != null); assertThat(fieldGroupBy.getName(), is("artist_id")); final LayoutGroup groupSecondaries = groupby.getSecondaryFields(); assertTrue(groupSecondaries != null); final List<LayoutItem> innerItems = groupby.getItems(); assertTrue(innerItems != null); final int numInnerItems = safeLongToInt(innerItems.size()); assertEquals(2, numInnerItems); layoutItem = innerItems.get(0); assertTrue(layoutItem != null); assertTrue(layoutItem instanceof LayoutItemField); LayoutItemField field = (LayoutItemField) layoutItem; assertTrue(field != null); assertThat(field.getName(), is("name")); assertThat(field.getGlomType(), is(Field.GlomFieldType.TYPE_TEXT)); layoutItem = innerItems.get(1); assertTrue(layoutItem != null); assertTrue(layoutItem instanceof LayoutItemField); field = (LayoutItemField) layoutItem; assertTrue(field != null); assertThat(field.getName(), is("year")); assertThat(field.getGlomType(), is(Field.GlomFieldType.TYPE_NUMERIC)); } // Test thread class that runs all the tests. private class TestThread implements Runnable { @Override public void run() { for (int i = 0; i < 20; i++) { testDocumentInfo(); testGetNumericFormat(); testLayoutItemText(); //TODO: testLayoutItemImage(), also testing that it has the expected layout path. testGetSuitableTableToViewDetails(); testReadLayoutListInfo(); testReadTableFieldSizes(); testReadTableNames(); testUsesRelationshipMethods(); } } } /* * Tests threaded access. */ @Test public void testThreadedAccess() throws InterruptedException { // create the threads final Thread thread1 = new Thread(new TestThread()); final Thread thread2 = new Thread(new TestThread()); final Thread thread3 = new Thread(new TestThread()); final Thread thread4 = new Thread(new TestThread()); // start the threads thread1.start(); thread2.start(); thread3.start(); thread4.start(); // wait for the treads to finish try { thread1.join(); } catch (final InterruptedException e) { System.out.println("Thread 1 had a problem finishing. " + e); throw e; } try { thread2.join(); } catch (final InterruptedException e) { System.out.println("Thread 2 had a problem finishing. " + e); throw e; } try { thread3.join(); } catch (final InterruptedException e) { System.out.println("Thread 3 had a problem finishing. " + e); throw e; } try { thread4.join(); } catch (final InterruptedException e) { System.out.println("Thread 4 had a problem finishing. " + e); throw e; } } /* * This method safely converts longs from libglom into ints. This method was taken from stackoverflow: * * http://stackoverflow.com/questions/1590831/safely-casting-long-to-int-in-java */ private static int safeLongToInt(final long l) { if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) { throw new IllegalArgumentException(l + " cannot be cast to int without changing its value."); } return (int) l; } }