Skip to content
Fabio Simeoni edited this page Feb 19, 2015 · 4 revisions

There are many ways to process the tables you've made or parsed from CSV data. All of them assume you know what tables are made of.

Unsurprisingly enough, tables are made of Columns and Rows, with a few twists.

Columns

You get to the columns of a table as you;d expect to:

List<Column> columns = table.columns();

and it's right at this point that we need to clear the ground from wrong assumptions: tabular's notion of what is a table is closer to what you find in CSV datafiles than in relational databases. In particular

columns indicate row structure, they neither prescribe it nor necessarily describe it in full: rows may have more or less columns than the table indicate. Columns are no "schemas".

Thus tabular's tables do not enforce uniformity, they are as "semi-structured" as the CSV they model.

note: this does not mean that tables cannot be perfectly regular. Only that regularity is on you, tabular will not help you keep it (nor storage-optimise for it).

What are columns good for then? They're good to "drive" processes - parsing, serialisation, as well as your own processes) -- by capturing what information most rows are most likely to contain.

So columns convey semantics. They do that first and foremost with a name.

Column col = col("iso3");

...col.name()...;

When a name is not enough (i.e. quite often), they can contain additional properties.

Properties

For example, you can mark a column that contain "codes" (for some notion of codes), and indicate somehow that codes are numbers:

col.properties().add("code","number");

tabular does not know what all that means, of course. Your code might though, and that's what properties are for: move semantic from code components that observe it, to other code components downstream that may react to their presence.

In the example above, we're just "tagging" the column, but properties are in fact key-value pairs:

col.properties().add(prop("key","val"),...);

again, the value here is a string, but you can store any object worth consuming later in a property. Indeed, there are methods to inspect the type of a property value and to get back the value as an instance of that type:

if (prop.is(MyClass.class)) ....
...
MyClass mv = prop.as(MyClass.class);

and there are of course plenty of methods to remove, check, and lookup properties from columns:

 Properties ps = col.properties();
 
 ps.prop("name");
 ps.propOr("name","some fallback value");
 ps.has("name1","name2",...);
 ps.remove("name1", "name2",...);
 ...ps.size()...
 ...ps.empty()...

All of the above works in bulk, with both varargs and Iterable parameters so that you don't get to adapt jets in the middle of your code. And you can chain where it makes sense. Check the documentation in Properties and Property for the boring details.

Rows

Rows are only a tiny bit more glamorous that columns, sadly. They essentially wrap String maps: you can get, set, remove, and check columns as you'd expect:

 row.get("c1");
 row.getOr("c1","some fallback value");
 row.set("c1","newval");
 row.remove("c1");
 row.has("c1")

Like properties, all of the above works in bulk, with both varargs and Iterable parameters so that you don't get to adapt jets in the middle of your code. And like properties again, you can chain where it makes sense:

 if (row.has("c1","c2"))
   row.set("c3","v3").remove("c4","c5");

Additionally, you can merge in other Rows:

row.merge(row2,row3,...);

or extract "sub-rows" of given columns:

Row sub = row.extract("c2","c3");

You can iterate over rows:

for (String val : row) ...

or stream their values:

r.stream()....

again, with shortcuts:

r.forEach(v -> ...);

all of above with usual overloads.

Finally, you con iterate directly over (col,value) pairs:

r.forEach((c,v) -> ...);

That's it!

Clone this wiki locally