Click here to Skip to main content
Click here to Skip to main content

DataSet - A Polymorph Collection

, 11 Jul 2013
Rate this:
Please Sign up or sign in to vote.
A set of classes providing a polymorphic data structure.

Introduction 

The DataSet is a simple class that holds items of any type. I initially used it for providing data to the client layer, encapsulating the server side functionality by only exposing data. This then got expanded with the ConfigData, a wrapped DataSet that provides configuration data and enforces reading all the items. 

This article describes the package of classes I use to support the DataSet. On its own, this isn't much, but I realised that a lot of other subjects I wanted to post articles on required this as it is my de-facto structure for throwing data around. 

Background 

It is often the case that a class has no function, just value. Well over time, I grew tired of writing myriad data classes with nothing but accessor methods. So based on a design I had used in various jobs, I went about building my own. 

Base Classes

The structure is simple as can be. A DataSet contains a set of DataItem objects. Each item takes a name/value pair and once created is immutable. As a result of getting stung around trying to use generics, I shifted the design so that the item holds an Object and the class itself ensures safe casting, rather than having to deal with it at a higher level.

In the DataSet, items can be retrieved as an object or the value accessed directly; this saves on a lot of null checks and method chaining.

The 'native' types that can be safely called from the DataSet and DataItem are all listed in enum ValueType. All other types are treated as an Object and the consumer is responsible for managing them safely. 

There are then two wrapper classes. The ConfigData is used for loading configuration from a file for an application and SealedDataSet provides read only access to a DataSet

Transport Layer 

The two major uses I have for the DataSet are communication and persistence. For this I provide two classes that read and write the data. 

DataReader is used to take an inbound String from a BufferedReader and turn it into a DataSet. The reverse is performed by DataWriter,  turning a DataSet into a String and writing it a  BufferedWritter. The format of these strings is nice and simple:

An example of the format, taken from the JavaDoc, is:

# comments can be added at any point and each
# item is written thus:
# name t value
example {
# Boolean -
   isMale ? TRUE
# DataSet -
   subBlock {
      item - simple text.
   } 
# Date -
   dateWriten @ 2013-02-27 12:00:25.3789Z
# Double -
   weight $ 75.3
# Integer -
   age % 42
# String [without reserved characters] -
   name - William Norman-Walker
# String [with reserved chracters] -
   longText \
\# this will all be read as\
it \@ contains all the special chracters \\ escaped\
\{ so the parser can read them \}.\
all for \$15.00 \@ \-50\% discount
} 

It is a bit like a few other formats I know; but that's how it evolved. For simple config files, the type character can be omitted and is treated as a string. The extended format is actually overkill, and simply using a backslash on the line terminator is enough for it to be parsed cleanly. 

Using the code

So how do I use it? The first way is for loading configuration options. I store the config for an app in a data file and then load it in at start up: }/**

 * Standard Entry point.
 * @param args
 */
public static void main (String[] args) {
    DataReader reader = null;
    try {
        reader = new DataReader(new File("demmo.config"));
        ConfigData config = new ConfigData(reader.read());
        App app = new Appendable(config);
        config.close();
    } catch (DataException ex) {
        System.err.print(ex);
    } catch (java.io.IOException ex) {
        System.err.print(ex);
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException ex) {
                System.err.print(ex);
            }
        }
    }
} 

I am not a great fan of throwing exceptions, but here I think it does make sense. For consideration would be a constructor for ConfigData that takes a file and deals with all the underlying problems.

Points of Interest

I use these classes in a lot in the stuff I write. The purpose of this article is that I will not have to re-visit this in future. For those interested, the next article should be on an expression evaluator that uses a DataSet to find variable names. 

History 

  • 2013-03 - Initial submission to CodeProject.
  • 2013-03-13 - Updated code, bug fix in toString() of DataItem
  • 2013-07-11 - Updated code, bug fix in get(key) in SealedDataItem

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Nagy Vilmos
President Belligerent Bad Tempered Old Fools Club
United Kingdom United Kingdom
Do not tell anyone I am not Hungarian. It's a huge secret.
I have worked across too many platforms over the years - COBOL, Pascal, C, C++, VB3-6, C# and java are some of them - and now I just write pretty front ends for users with less wit than a gumby.
 
If I had a pound for everything I've learned over the years, I'd have £12,879.73
 
Semper ebrius, quantum variat.
Follow on   Twitter   LinkedIn

Comments and Discussions

 
QuestionUsage Examples? PinmemberGreg Niswonger12-Mar-13 11:34 
AnswerRe: Usage Examples? PinmemberNagy Vilmos12-Mar-13 21:18 
GeneralRe: Usage Examples? PinmemberGreg Niswonger13-Mar-13 9:36 
GeneralMy vote of 5 Pinmemberlinuxjr7-Mar-13 4:52 
GeneralMy vote of 5 PinmemberThe Bhai7-Mar-13 4:47 
GeneralRe: My vote of 5 PinmemberNagy Vilmos7-Mar-13 4:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 11 Jul 2013
Article Copyright 2013 by Nagy Vilmos
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid