You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@empire-db.apache.org by do...@apache.org on 2022/01/26 19:45:03 UTC

[empire-db] branch version3 updated: EMPIREDB-367 DataListFactory interface and impl

This is an automated email from the ASF dual-hosted git repository.

doebele pushed a commit to branch version3
in repository https://gitbox.apache.org/repos/asf/empire-db.git


The following commit(s) were added to refs/heads/version3 by this push:
     new 89f2e52  EMPIREDB-367 DataListFactory interface and impl
89f2e52 is described below

commit 89f2e5207f90c7b9ae6406fedb5671d7d64b3401
Author: Rainer Döbele <do...@apache.org>
AuthorDate: Wed Jan 26 20:45:00 2022 +0100

    EMPIREDB-367 DataListFactory interface and impl
---
 .../org/apache/empire/samples/db/SampleApp.java    |  13 +--
 .../org/apache/empire/data/list/DataListEntry.java |  10 +-
 .../apache/empire/data/list/DataListFactory.java   |  16 +++
 .../empire/data/list/DataListFactoryImpl.java      | 113 +++++++++++++++++++++
 .../org/apache/empire/data/list/DataListHead.java  |  90 +---------------
 .../main/java/org/apache/empire/db/DBUtils.java    |  41 +++++---
 6 files changed, 173 insertions(+), 110 deletions(-)

diff --git a/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java b/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
index 13eb058..724fc15 100644
--- a/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
+++ b/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
@@ -131,12 +131,6 @@ public class SampleApp
             // SECTION 5 AND 6: Populate Database and modify Data
 			populateAndModify(clearExistingData);
 
-            /*
-            int idEmp = testTransactionCreate(idDevDep);
-            testTransactionUpdate(idEmp);
-            testTransactionDelete(idEmp);
-            */
-
             // SECTION 7: Option 1: Query Records and print tab-separated
             log.info("Step 8 Option 1: queryRecords() / Tab-Output");
             queryRecords(QueryType.Reader); // Tab-Output
@@ -158,6 +152,13 @@ public class SampleApp
 			// SECTION 10: Use Bean Result to query beans
 			queryBeans();
 			
+
+            /*
+            int idEmp = testTransactionCreate(idDevDep);
+            testTransactionUpdate(idEmp);
+            testTransactionDelete(idEmp);
+            */
+			
             // Finally, commit any changes
             context.commit();
             
diff --git a/empire-db/src/main/java/org/apache/empire/data/list/DataListEntry.java b/empire-db/src/main/java/org/apache/empire/data/list/DataListEntry.java
index 3121867..98a4ae3 100644
--- a/empire-db/src/main/java/org/apache/empire/data/list/DataListEntry.java
+++ b/empire-db/src/main/java/org/apache/empire/data/list/DataListEntry.java
@@ -26,21 +26,21 @@ public class DataListEntry implements RecordData, Serializable
     
     private static final Logger log  = LoggerFactory.getLogger(DataListEntry.class);
     
-    protected final DataListHead<? extends DataListEntry> head;
+    protected final DataListHead head;
     protected final Object values[];
     protected int rownum;
     
-    public DataListEntry(DataListHead<? extends DataListEntry> head, int rownum, Object values[])
+    public DataListEntry(DataListHead head, int rownum, Object values[])
     {
         this.head = head;
         this.rownum = rownum;
         this.values = values;
     }
     
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    public <H extends DataListHead> H getHead()
+    @SuppressWarnings("unchecked")
+    public <T extends DataListHead> T getHead()
     {
-        return (H)this.head;
+        return (T)this.head;
     }
     
     public Object[] getKey(Entity entity)
diff --git a/empire-db/src/main/java/org/apache/empire/data/list/DataListFactory.java b/empire-db/src/main/java/org/apache/empire/data/list/DataListFactory.java
new file mode 100644
index 0000000..d768721
--- /dev/null
+++ b/empire-db/src/main/java/org/apache/empire/data/list/DataListFactory.java
@@ -0,0 +1,16 @@
+package org.apache.empire.data.list;
+
+import java.util.List;
+
+import org.apache.empire.data.RecordData;
+
+public interface DataListFactory<T extends DataListEntry>
+{
+    void prepareQuery();
+    
+    List<T> newList(int capacity);
+
+    T newEntry(int rownum, RecordData dataRow);
+    
+    void completeQuery(List<T> list);
+}
diff --git a/empire-db/src/main/java/org/apache/empire/data/list/DataListFactoryImpl.java b/empire-db/src/main/java/org/apache/empire/data/list/DataListFactoryImpl.java
new file mode 100644
index 0000000..980a7ae
--- /dev/null
+++ b/empire-db/src/main/java/org/apache/empire/data/list/DataListFactoryImpl.java
@@ -0,0 +1,113 @@
+package org.apache.empire.data.list;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.empire.data.ColumnExpr;
+import org.apache.empire.data.RecordData;
+import org.apache.empire.exceptions.InternalException;
+import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.NotSupportedException;
+import org.apache.empire.exceptions.UnsupportedTypeException;
+
+public class DataListFactoryImpl<T extends DataListEntry> implements DataListFactory<T>
+{
+    /**
+     * findEntryConstructor
+     * @param listEntryClass
+     * @param listHeadClass
+     * @return the constructor
+     */
+    @SuppressWarnings("unchecked")
+    protected static <T extends DataListEntry> Constructor<T> findEntryConstructor(Class<?> listEntryClass, Class<? extends DataListHead> listHeadClass)
+    {
+        try
+        {   // Alternatively use ClassUtils.findMatchingAccessibleConstructor(listEntryClass, new Class<?>[] { listHeadClass, int.class, Object[].class });
+            return (Constructor<T>) listEntryClass.getDeclaredConstructor(listHeadClass, int.class, Object[].class);
+        }
+        catch (NoSuchMethodException | SecurityException e)
+        {
+            throw new UnsupportedTypeException(listEntryClass);
+        }
+    }
+
+    protected final Constructor<T> constructor;
+    protected final DataListHead head;
+
+    /**
+     * Constructs a DataListHead based on an DataListEntry constructor
+     * @param constructor the DataListEntry constructor
+     * @param columns the list entry columns
+     */
+    public DataListFactoryImpl(Constructor<T> constructor, DataListHead head) 
+    {
+        this.constructor = constructor;
+        this.head = head;
+    }
+    
+    public DataListFactoryImpl(Class<T> listEntryClass, DataListHead head) 
+    {
+        this(findEntryConstructor(listEntryClass, DataListHead.class), head);
+    }
+    
+    @Override
+    public void prepareQuery()
+    {
+        /* Nothing */
+    }
+
+    @Override
+    public List<T> newList(int capacity)
+    {
+        return new ArrayList<T>(capacity);
+    }
+
+    @Override
+    public T newEntry(int rownum, RecordData dataRow)
+    {   // check
+        ColumnExpr[] columns = head.getColumns();
+        if (columns.length!=dataRow.getFieldCount())
+            throw new InvalidArgumentException("dataRow", dataRow);
+        // copy values
+        Object[] values = new Object[columns.length];
+        for (int i=0; i<columns.length; i++)
+            values[i] = dataRow.getValue(i);
+        // create
+        return newEntry(rownum, values);
+    }
+
+    protected T newEntry(int rownum, Object[] values)
+    {   try
+        {   // must override newEntry if no constructor is provided
+            if (constructor==null)
+                throw new NotSupportedException(this, "newEntry");
+            // create item
+            return constructor.newInstance(head, rownum, values);
+        }
+        catch (InstantiationException e)
+        {
+            throw new InternalException(e);
+        }
+        catch (IllegalAccessException e)
+        {
+            throw new InternalException(e);
+        }
+        catch (IllegalArgumentException e)
+        {
+            throw new InternalException(e);
+        }
+        catch (InvocationTargetException e)
+        {
+            throw new InternalException(e);
+        }
+    }
+    
+    @Override
+    public void completeQuery(List<T> list)
+    {
+        /* Nothing */
+    }
+
+}
diff --git a/empire-db/src/main/java/org/apache/empire/data/list/DataListHead.java b/empire-db/src/main/java/org/apache/empire/data/list/DataListHead.java
index 3844794..174ad06 100644
--- a/empire-db/src/main/java/org/apache/empire/data/list/DataListHead.java
+++ b/empire-db/src/main/java/org/apache/empire/data/list/DataListHead.java
@@ -4,115 +4,31 @@
 package org.apache.empire.data.list;
 
 import java.io.Serializable;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 
 import org.apache.empire.commons.ObjectUtils;
 import org.apache.empire.commons.Options;
 import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.ColumnExpr;
-import org.apache.empire.data.RecordData;
-import org.apache.empire.exceptions.InternalException;
-import org.apache.empire.exceptions.InvalidArgumentException;
-import org.apache.empire.exceptions.NotSupportedException;
-import org.apache.empire.exceptions.UnsupportedTypeException;
 
-public class DataListHead<T extends DataListEntry> implements Serializable
+public class DataListHead implements Serializable
 {
     private static final long serialVersionUID = 1L;
     // private static final Logger log  = LoggerFactory.getLogger(DataListHead.class);
     
-    final Constructor<T> constructor;
-    final ColumnExpr[] columns;
+    protected final ColumnExpr[] columns;
     
     protected String columnSeparator = "\t";
-    
-    /**
-     * findEntryConstructor
-     * @param listEntryClass
-     * @param listHeadClass
-     * @return the constructor
-     */
-    @SuppressWarnings("unchecked")
-    protected static <T extends DataListEntry> Constructor<T> findEntryConstructor(Class<?> listEntryClass, @SuppressWarnings("rawtypes") Class<? extends DataListHead> listHeadClass)
-    {
-        /*
-        Constructor<?> constructor = ClassUtils.findMatchingAccessibleConstructor(listEntryClass, new Class<?>[] { listHeadClass, int.class, Object[].class });
-        if (constructor==null)
-            throw new UnsupportedTypeException(listEntryClass);
-        return constructor;
-        */
-        try
-        {   // Find the constructor
-            return (Constructor<T>)listEntryClass.getDeclaredConstructor(listHeadClass, int.class, Object[].class);
-        }
-        catch (NoSuchMethodException e)
-        {
-            throw new UnsupportedTypeException(listEntryClass);
-        }
-        catch (SecurityException e)
-        {
-            throw new UnsupportedTypeException(listEntryClass);
-        }
-    }
 
     /**
      * Constructs a DataListHead based on an DataListEntry constructor
      * @param constructor the DataListEntry constructor
      * @param columns the list entry columns
      */
-    public DataListHead(Constructor<T> constructor, ColumnExpr[] columns) 
+    public DataListHead(ColumnExpr[] columns) 
     {
-        this.constructor = constructor;
         this.columns = columns;
     }
     
-    public DataListHead(Class<T> listEntryClass, ColumnExpr[] columns) 
-    {
-        this(findEntryConstructor(listEntryClass, DataListHead.class), columns);
-    }
-    
-    public T newEntry(int rownum, Object[] values)
-    {   try
-        {   // check
-            if (columns.length!=values.length)
-                throw new InvalidArgumentException("values", values);
-            // must override newEntry if no listEntryClass is provided
-            if (constructor==null)
-                throw new NotSupportedException(this, "newEntry");
-            // create item
-            return constructor.newInstance(this, rownum, values);
-        }
-        catch (InstantiationException e)
-        {
-            throw new InternalException(e);
-        }
-        catch (IllegalAccessException e)
-        {
-            throw new InternalException(e);
-        }
-        catch (IllegalArgumentException e)
-        {
-            throw new InternalException(e);
-        }
-        catch (InvocationTargetException e)
-        {
-            throw new InternalException(e);
-        }
-    }
-
-    public final T newEntry(int rownum, RecordData data)
-    {   // check
-        if (columns.length!=data.getFieldCount())
-            throw new InvalidArgumentException("data", data);
-        // copy values
-        Object[] values = new Object[columns.length];
-        for (int i=0; i<columns.length; i++)
-            values[i] = data.getValue(i);
-        // create
-        return newEntry(rownum, values);
-    }
-    
     public ColumnExpr[] getColumns()
     {
         return columns; 
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBUtils.java b/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
index 1c2fc3d..6b15117 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
@@ -12,6 +12,8 @@ import org.apache.empire.commons.Options;
 import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.DataType;
 import org.apache.empire.data.list.DataListEntry;
+import org.apache.empire.data.list.DataListFactory;
+import org.apache.empire.data.list.DataListFactoryImpl;
 import org.apache.empire.data.list.DataListHead;
 import org.apache.empire.db.context.DBContextAware;
 import org.apache.empire.db.exceptions.ConstraintViolationException;
@@ -642,30 +644,33 @@ public class DBUtils implements DBContextAware
     }
 
     /**
-     * Crates a default DataListHead for a DataListEntry class
+     * Crates a default DataListFactory for a DataListEntry class
      * The DataListEntry class must provide the following constructor
-     *      DataListEntry(DataListHead<? extends DataListEntry> head, int rownum, Object values[])
+     *      DataListEntry(DataListFactory<? extends DataListEntry> head, int rownum, Object values[])
      * @param entryClass the entryClass for which to create the list head 
      * @return
      */
-    protected <T extends DataListEntry> DataListHead<T> createDefaultDataListHead(DBCommand cmd, Class<T> entryClass) 
+    protected <T extends DataListEntry> DataListFactory<T> createDefaultDataListFactory(Class<T> entryClass, DataListHead head) 
     {
-        return new DataListHead<T>(entryClass, cmd.getSelectExprList());
+        return new DataListFactoryImpl<T>(entryClass, head);
     }
     
     /**
      * Executes a query and returns a list of DataListEntry items
      * @param sqlCmd the SQL-Command for the query
-     * @param listHead the HeadInfo to be used for each list item
+     * @param factory the Factory to be used for each list item
      * @param first the number of records to skip from the beginning of the result
      * @param pageSize the maximum number of item to return
      * @return the list 
      */
-    public <T extends DataListEntry> List<T> queryDataList(DBCommand cmd, DataListHead<T> listHead, int first, int pageSize)
+    public <T extends DataListEntry> List<T> queryDataList(DBCommand cmd, DataListFactory<T> factory, int first, int pageSize)
     {
+        List<T> list = null;
         DBReader r = new DBReader(context);
         try
-        {   // check pageSize
+        {   // prepare
+            factory.prepareQuery();
+            // check pageSize
             if (pageSize==0)
             {   log.warn("PageSize must not be 0. Setting to -1 for all records!");
                 pageSize = -1;
@@ -690,12 +695,12 @@ public class DBUtils implements DBContextAware
             }
             // Create a list of data entries
             int maxCount = (pageSize>=0) ? pageSize : MAX_QUERY_ROWS;
-            ArrayList<T> list = new ArrayList<T>((pageSize>=0) ? pageSize : 10);
+            list = factory.newList((pageSize>=0) ? pageSize : 10);
             // add data
             int rownum = 0;
             while (r.moveNext() && maxCount != 0)
             {   // Create bean an init
-                T entry = listHead.newEntry(++rownum, r);
+                T entry = factory.newEntry(++rownum, r);
                 if (entry==null)
                     continue;
                 // add entry
@@ -714,17 +719,28 @@ public class DBUtils implements DBContextAware
             return list;
         }
         finally
-        {
+        {   // close reader
             r.close();
+            // complete
+            if (list!=null)
+                factory.completeQuery(list);
         }
     }
+
+    /**
+     * Queries a list of DataListEntry items
+     */
+    public final <T extends DataListEntry> List<T> queryDataList(DBCommand cmd, Class<T> entryClass, DataListHead head)
+    {
+        return queryDataList(cmd, createDefaultDataListFactory(entryClass, head), 0, MAX_QUERY_ROWS);
+    }
     
     /**
      * Queries a list of DataListEntry items
      */
     public final <T extends DataListEntry> List<T> queryDataList(DBCommand cmd, Class<T> entryClass)
     {
-        return queryDataList(cmd, createDefaultDataListHead(cmd, entryClass), 0, MAX_QUERY_ROWS);
+        return queryDataList(cmd, entryClass, new DataListHead(cmd.getSelectExprList()));
     }
     
     /**
@@ -741,7 +757,8 @@ public class DBUtils implements DBContextAware
      */
     public final <T extends DataListEntry> T queryDataEntry(DBCommand cmd, Class<T> entryClass, boolean forceResult)
     {
-        List<T> dle = queryDataList(cmd, createDefaultDataListHead(cmd, entryClass), 0, 1);
+        DataListHead head = new DataListHead(cmd.getSelectExprList());
+        List<T> dle = queryDataList(cmd, createDefaultDataListFactory(entryClass, head), 0, 1);
         if (dle.isEmpty())
         {   if (forceResult)
                 throw new QueryNoResultException(cmd.getSelect());