Skip to content
Permalink
Browse files

[core] Support nullable flag for meta-data of row column.

```java
import acolyte.RowList2;
import acolyte.RowLists;

RowList2.Impl<String,Float> l1 =
  RowLists.rowList2(String.class, Float.class).
  withNullable(1, true); // First column is nullable

import acolyte.RowList;
import acolyte.Column;

Column<String> meta1 = new Column<String>(String.class, "a", true);

RowList2.Impl<String,Float> l2 =
  RowLists.rowLists2(meta1, RowList.Column(Float.class, "b"));

import static acolyte.RowList.Column

RowList2.Impl<String,Float> l3 =
  RowLists.rowLists2(Column(String.class, "a").withNullable(true),
    Column(Float.class, "b"));
```
  • Loading branch information
cchantep
cchantep committed Jan 11, 2014
1 parent 2aae84f commit 4edb03ec7b48e89e3219fe898f667c63cdd356a8
@@ -0,0 +1,65 @@
package acolyte;

/**
* Column meta data.
*
* @author Cedric Chantepie
*/
public final class Column<T> {
/**
* Column class
*/
public final Class<T> columnClass;

/**
* Column name/label
*/
public final String name;

/**
* Column is nullable? (default: false)
*/
public final boolean nullable;

// --- Constructors ---

/**
* Bulk constructor.
*/
Column(final Class<T> columnClass,
final String name,
final boolean nullable) {

if (columnClass == null) {
throw new IllegalArgumentException("No column class");
} // end of if

if (name == null || name.length() == 0) {
throw new IllegalArgumentException("Invalid column name: " +
name);

} // end of if

this.columnClass = columnClass;
this.name = name;
this.nullable = nullable;
} // end of <init>

/**
* Creates a not nullable column.
*/
Column(final Class<T> columnClass, final String name) {
this(columnClass, name, false);
} // end of <init>

// ---

/**
* Returns similar metadata, but with specified |nullable| flag.
*
* @param nullable Whether new metadata is nullable
*/
public Column withNullable(final boolean nullable) {
return new Column(this.columnClass, this.name, nullable);
} // end of withNullable
} // end of class Column
@@ -23,7 +23,6 @@
* Type-safe list of row.
*
* @author Cedric Chantepie
* @todo Add nullable property to Column
*/
public abstract class RowList<R extends Row> {

@@ -45,9 +44,20 @@
*
* @param columnIndex Index of column (first index is 1)
* @param label Column name/label
* @see Column#name
*/
public abstract RowList<R> withLabel(int columnIndex, String label);

/**
* Returns copy of row list with updated metadata,
* including whether specified column is |nullable|.
*
* @param columnIndex Index of column (first index is 1)
* @param nullable Is column nullable?
* @see Column#nullable
*/
public abstract RowList<R> withNullable(int columnIndex, boolean nullable);

/**
* Returns result set from these rows.
*
@@ -91,6 +101,13 @@ public QueryResult asResult() {
*/
public abstract Map<String,Integer> getColumnLabels();

/**
* Gets column mappings, from index to nullable flag.
*
* @return Column mappings, or empty map (not null) if none
*/
public abstract Map<Integer,Boolean> getColumnNullables();

// --- Shared ---

/**
@@ -123,6 +140,12 @@ public QueryResult asResult() {
private final Map<String,Integer> labels =
new HashMap<String,Integer>(0);

/**
* Empty flags
*/
private final Map<Integer,Boolean> nullables =
new HashMap<Integer,Boolean>(0);

// --- Constructors ---

/**
@@ -142,18 +165,23 @@ private NilRowList() { }
/**
* Returns unchanged nil row list.
*/
public RowList<Row.Nothing> append(final Row.Nothing row) {
public NilRowList append(final Row.Nothing row) { return this; }

/**
* Returns unchanged nil row list.
*/
public NilRowList withLabel(final int columnIndex, final String label) {
return this;
} // end of append
} // end of withLabel

/**
* Returns unchanged nil row list.
*/
public RowList<Row.Nothing> withLabel(final int columnIndex,
final String label) {
public NilRowList withNullable(final int columnIndex,
final boolean nullable) {

return this;
} // end of withLabel
} // end of withNullable

/**
* Returns empty list of columns classes.
@@ -168,6 +196,13 @@ private NilRowList() { }
public Map<String,Integer> getColumnLabels() {
return this.labels;
} // end of getColumnLabels

/**
* Returns empty list of nullable flags.
*/
public Map<Integer,Boolean> getColumnNullables() {
return this.nullables;
} // end of getColumnNullables
} // end of class Nil

/**
@@ -182,39 +217,6 @@ private NilRowList() { }
return new Column<T>(columnClass, name);
} // end of column

/**
* Column definition.
*/
public static final class Column<T> {
/**
* Column class
*/
public final Class<T> columnClass;

/**
* Column name/label
*/
public final String name;

/**
* Bulk constructor.
*/
private Column(final Class<T> columnClass, final String name) {
if (columnClass == null) {
throw new IllegalArgumentException("No column class");
} // end of if

if (name == null || name.length() == 0) {
throw new IllegalArgumentException("Invalid column name: " +
name);

} // end of if

this.columnClass = columnClass;
this.name = name;
} // end of <init>
} // end of Column

/**
* Result set made from list of row.
*
@@ -1138,6 +1140,7 @@ public ResultSetMetaData getMetaData() throws SQLException {
public final class RowListMetaData implements ResultSetMetaData {
final List<Class<?>> columnClasses;
final Map<String,Integer> columnLabels;
final Map<Integer,Boolean> columnNullables;

// --- Constructors ---

@@ -1147,6 +1150,7 @@ public ResultSetMetaData getMetaData() throws SQLException {
private RowListMetaData() {
this.columnClasses = getColumnClasses();
this.columnLabels = getColumnLabels();
this.columnNullables = getColumnNullables();
} // end of <init>

// ---
@@ -1236,8 +1240,13 @@ public boolean isSigned(final int column) throws SQLException {
* {@inheritDoc}
*/
public int isNullable(final int column) throws SQLException {
// TODO: See anorm.RowSpec
return ResultSetMetaData.columnNullableUnknown;
final Boolean b = this.columnNullables.get(column);

return (b == null) ? ResultSetMetaData.columnNullableUnknown :
(Boolean.TRUE.equals(b))
? ResultSetMetaData.columnNullable
: ResultSetMetaData.columnNoNulls;

} // end of isNullable

/**
@@ -39,7 +39,7 @@ public abstract class RowList#N#<#CP#,UPDATED extends RowList#N#<#CP#,?>>

copy.add(row);

return factory().rowList(#GC#, copy, getColumnLabels());
return factory().rowList(#GC#, copy, getColumnLabels(), getColumnNullables());
} // end of append

/**
@@ -57,9 +57,21 @@ public abstract class RowList#N#<#CP#,UPDATED extends RowList#N#<#CP#,?>>

cols.put(label, (Integer) columnIndex);

return factory().rowList(#GC#, getRows(), cols);
return factory().rowList(#GC#, getRows(), cols, getColumnNullables());
} // end of withLabel

/**
* {@inheritDoc}
*/
public UPDATED withNullable(final int columnIndex, final boolean nullable) {
final HashMap<Integer,Boolean> nls =
new HashMap<Integer,Boolean>(getColumnNullables());

nls.put(columnIndex, nullable);

return factory().rowList(#GC#, getRows(), getColumnLabels(), nls);
} // end of withNullable

// --- Inner classes ---

/**
@@ -69,8 +81,11 @@ public abstract class RowList#N#<#CP#,UPDATED extends RowList#N#<#CP#,?>>

/**
* Build row list, including |rows| with given column |labels|.
*
* @param nullables Nullable flags.
*/
public ROWLIST rowList(#CS#, final List<Row#N#<#CP#>> rows, final Map<String,Integer> labels);
public ROWLIST rowList(#CS#, final List<Row#N#<#CP#>> rows, final Map<String,Integer> labels, final Map<Integer,Boolean> nullables);

} // end of interface Factory

/**
@@ -89,6 +104,11 @@ public abstract class RowList#N#<#CP#,UPDATED extends RowList#N#<#CP#,?>>
*/
final Map<String,Integer> colNames;

/**
* Nullable flags
*/
final Map<Integer,Boolean> colNullables;

#PS#

/**
@@ -103,7 +123,7 @@ public abstract class RowList#N#<#CP#,UPDATED extends RowList#N#<#CP#,?>>
*
* @throws IllegalArgumentException if rows is null
*/
Impl(#CS#, final List<Row#N#<#CP#>> rows, final Map<String,Integer> colNames) {
Impl(#CS#, final List<Row#N#<#CP#>> rows, final Map<String,Integer> colNames, final Map<Integer,Boolean> colNullables) {

#IC#

@@ -115,8 +135,13 @@ public abstract class RowList#N#<#CP#,UPDATED extends RowList#N#<#CP#,?>>
throw new IllegalArgumentException("Invalid names");
} // end of if

if (colNullables == null) {
throw new IllegalArgumentException("Invalid nullable flags");
} // end of if

this.rows = Collections.unmodifiableList(rows);
this.colNames = Collections.unmodifiableMap(colNames);
this.colNullables = Collections.unmodifiableMap(colNullables);

// Column classes
final ArrayList<Class<?>> colClasses = new ArrayList<Class<?>>();
@@ -130,7 +155,7 @@ public abstract class RowList#N#<#CP#,UPDATED extends RowList#N#<#CP#,?>>
* No-arg constructor.
*/
Impl(#CS#) {
this(#CA#, new ArrayList<Row#N#<#CP#>>(), new HashMap<String,Integer>());
this(#CA#, new ArrayList<Row#N#<#CP#>>(), new HashMap<String,Integer>(), new HashMap<Integer,Boolean>());
} // end of <init>

// ---
@@ -142,8 +167,8 @@ public abstract class RowList#N#<#CP#,UPDATED extends RowList#N#<#CP#,?>>
*/
RowList#N#.Factory<#CP#, Impl<#CP#>> factory() {
return new RowList#N#.Factory<#CP#,Impl<#CP#>>() {
public Impl<#CP#> rowList(#CS#, final List<Row#N#<#CP#>> rows, final Map<String,Integer> colNames) {
return new Impl(#PSC#, rows, colNames);
public Impl<#CP#> rowList(#CS#, final List<Row#N#<#CP#>> rows, final Map<String,Integer> colNames, final Map<Integer,Boolean> colNullables) {
return new Impl(#PSC#, rows, colNames, colNullables);
}
};
} // end of factory
@@ -162,5 +187,10 @@ public abstract class RowList#N#<#CP#,UPDATED extends RowList#N#<#CP#,?>>
* {@inheritDoc}
*/
public List<Class<?>> getColumnClasses() { return this.colClasses; }

/**
* {@inheritDoc}
*/
public Map<Integer,Boolean> getColumnNullables() { return this.colNullables; }
} // end of class Impl
} // end of class RowList#N#

0 comments on commit 4edb03e

Please sign in to comment.
You can’t perform that action at this time.