zaterdag 25 januari 2014

Using Java Enums as a record description, and access them in a generic way, using reflection.

 I love to use java enums in my software. 

You can use them as field-definitions for a datadictionary. 

for example:
public enum _ENUM_FIELDS {
        _SITE_NR('s', "Site"), _COUNTRY('c', "Country");

        public char id;
        public final String text;

        private _ENUM_FIELDS(char id, String text) {
            this.id = id;
            this.text = text;
        }

        @Override
        public String toString() {
            return getString(id, name(), text);
        }
    }
The enum _ENUM_FIELDS has 2 field-definitions, each entry has 3 attributes.

  • char id = the key of the field. This should be unique in a file-definition.
  • String text = The field description.
  • String Name = is not defined, but can be obtained by calling the name() method of the enum.

By using reflection, enums can be handled in a generic way. The class MaxEnum deals with this part. The class MaxEnumSort implements sorting an enum in various ways, based on the 3 attributes for an entry.

You should override the toString() method in the enum, and call the static function getString(), which calls MaxEnumSort, which sorts the fields within a record.

  •  MaxEnum              - handles enums in a generic way using reflection
  •  MaxEnumSort       - Sort an enum in various ways
  • GenericJavaEnumExample - small example to show the use of MaxEnum
  • MaxRecorderIniDD - example which I use in the application I'm writing now


----------------------------------------------------------------

package nl.yokoz.data;

public abstract class MaxEnumSort  {
    public enum _SORT_ORDER {
        _TEXT, _ID, _NAAM;
    }
    public static _SORT_ORDER sortOrder = _SORT_ORDER._NAAM;
    protected static String toString(char id, String name, String text) {
        switch (sortOrder) {
        case _ID:
            return id + "  " + name + "  " + text;
        case _NAAM:
            return name + "  " + id + "  " + text;
        case _TEXT:
            return text + "  " + id + "  " + name;
        }
        return "";
    }

}
----------------------------------------------------------------
package nl.yokoz.data;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

import nl.yokoz.data.MaxEnumSort._SORT_ORDER;

public class MaxEnum {

    private Class theEnum;

    public MaxEnum(Class aClass) {
        if (aClass.isEnum()) {
            theEnum = aClass;
        }
    }

    public void toSysOut() {
        final String[] enumFields = getEnumFields();
        if (enumFields != null) {
            System.out.println(theEnum.getName());
            System.out.println("Sorted on: " + MaxEnumSort.sortOrder);
            for (String enumField : enumFields) {
                System.out.println(enumField); // This will call toString in the
                                                // reflected enum. The final
                                                // text comes
                                                // from MaxEnumSort:toString.
            }
            System.out.println();
        }
    }

    public String[] getEnumFields() {
        String[] enumFields = null;
        if (theEnum != null) {
            List enumConstants =Arrays.asList(theEnum.getEnumConstants());
            enumFields = new String[enumConstants.size()];
            int i = 0;
            for (Object enumConstant : enumConstants) {
                enumFields[i++] = enumConstant.toString();
            }
            Arrays.sort(enumFields);
        }
        return enumFields;
    }

    public void showFields(boolean bNoConstants) {
        if (theEnum != null) {
            Field[] fields = getDeclaredFields(bNoConstants);
            for (Field field : fields) {
                System.out.println(field.toString());
            }
        }
    }

    public Field[] getDeclaredFields(boolean bNoConstants) {
        Field[] fields = theEnum.getDeclaredFields();
        if (!bNoConstants) {
            return fields;
        }
        int i = 0;
        int f = 0;
        int[] fieldIndexes = new int[fields.length];
        for (Field field : fields) {
            if (!field.isEnumConstant()) {
                fieldIndexes[f++] = i;
            }
            i++;
        }
        Field[] fieldsNoConstants = new Field[f];
        for (int j = 0; j < f; j++) {
            fieldsNoConstants[j] = fields[fieldIndexes[j]];
        }
        return fieldsNoConstants;
    }

    public void toSysOutAll() {
        for (_SORT_ORDER sortOrder : MaxEnumSort._SORT_ORDER.values()) {
            MaxEnumSort.sortOrder = sortOrder;
            toSysOut();
        }
    }

}
----------------------------------------------------------------

package nl.yokoz.maxrecorder.db.dd;

import nl.yokoz.data.MaxEnum;
import nl.yokoz.data.MaxEnumSort;

public class GenericJavaEnumExample extends MaxEnumSort {

    public enum _ENUM_FIELDS {
        _SITE_NR('s', "Site"), _COUNTRY('c', "Country"), _TIMEZONE('t', "TimeZone"), _LOCATION_ACTIVE('a', "Location Active");

        public char id;
        public final String text;

        private _ENUM_FIELDS(char id, String text) {
            this.id = id;
            this.text = text;
        }

        @Override
        public String toString() {
            return getString(id, name(), text);
        }

    }

    public static String getString(char id, String name, String text) {
        return toString(id, name, text); // call toString in MaxEnumSort, the
                                            // parent class.

    }

    public static void main(String[] args) {
        final MaxEnum maxEnum = new MaxEnum(GenericJavaEnumExample._ENUM_FIELDS.class);
        maxEnum.showFields(true);
        maxEnum.toSysOutAll();
    }

}

The output when running main() is:

public char nl.yokoz.maxrecorder.db.dd.GenericJavaEnumExample$_ENUM_FIELDS.id
public final java.lang.String nl.yokoz.maxrecorder.db.dd.GenericJavaEnumExample$_ENUM_FIELDS.text
private static final nl.yokoz.maxrecorder.db.dd.GenericJavaEnumExample$_ENUM_FIELDS[] nl.yokoz.maxrecorder.db.dd.GenericJavaEnumExample$_ENUM_FIELDS.ENUM$VALUES

nl.yokoz.maxrecorder.db.dd.GenericJavaEnumExample$_ENUM_FIELDS
Sorted on: _TEXT
Country  c  _COUNTRY
Location Active  a  _LOCATION_ACTIVE
Site  s  _SITE_NR
TimeZone  t  _TIMEZONE

nl.yokoz.maxrecorder.db.dd.GenericJavaEnumExample$_ENUM_FIELDS
Sorted on: _ID
a  _LOCATION_ACTIVE  Location Active
c  _COUNTRY  Country
s  _SITE_NR  Site
t  _TIMEZONE  TimeZone

nl.yokoz.maxrecorder.db.dd.GenericJavaEnumExample$_ENUM_FIELDS
Sorted on: _NAAM
_COUNTRY  c  Country
_LOCATION_ACTIVE  a  Location Active
_SITE_NR  s  Site
_TIMEZONE  t  TimeZone



----------------------------------------------------------------

package nl.yokoz.maxrecorder.db.dd;

import nl.yokoz.data.MaxEnum;
import nl.yokoz.data.MaxEnumSort;

public class MaxRecorderIniDD extends MaxEnumSort {

    public enum _FIELDS {
        _OUTPUTFILE_PREFIX('o', "OutputFilePrefix"), _SITE_NR('s', "Site"), _COUNTRY('c', "Country"), _TIMEZONE('t', "TimeZone"), _LOCATION_ACTIVE('a', "Location Active"), _AWAKE_HOUR('a', "AwakeHour"), _AWAKE_MINUTE('b', "AwakeMinuut"), _NO_SIZECHECK('c', "noSizeCheck"), _SHOW_TIMESTAMP('t', "ShowTimestamp"), _SLEEP_HOUR('h', "SleepHour"), _SLEEP_MINUTE('m', "SleepMinuut"), _EXTENTIE('e', "Extentie"), _CALC_FILENAME('q', "CalcFileName"), _IMAGE_SIZE('s', "Image size"), _LOCATIE_NR('l', "Locatie"), _CAPTURE_INTERVAL_SECONDS('i', "CaptureIntervalSeconds"), _OUTPUTFILE_POSTPREFIX('p', "OutputFilePostFix"), _LOCATION_NAME('n', "LocationName");

        public char id;
        public final String text;

        private _FIELDS(char id, String text) {
            this.id = id;
            this.text = text;
        }

        @Override
        public String toString() {
            return getString(id, name(), text);
        }

    }

    public static String getString(char id, String name, String text) {

         // call toString in MaxEnumSort, the parent class.
         return toString(id, name, text);

    }

    public static void main(String[] args) {
        final MaxEnum maxEnum = new MaxEnum(_FIELDS.class);
        // enable the following line, when you want to change the default
        // sortorder.
        // MaxEnumSort.sortOrder = _SORT_ORDER._TEXT;
        maxEnum.toSysOut();
        maxEnum.showFields(false);
        maxEnum.toSysOutAll();
    }

}

The output when running main() is:
nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS
Sorted on: _NAAM
_AWAKE_HOUR  a  AwakeHour
_AWAKE_MINUTE  b  AwakeMinuut
_CALC_FILENAME  q  CalcFileName
_CAPTURE_INTERVAL_SECONDS  i  CaptureIntervalSeconds
_COUNTRY  c  Country
_EXTENTIE  e  Extentie
_IMAGE_SIZE  s  Image size
_LOCATIE_NR  l  Locatie
_LOCATION_ACTIVE  a  Location Active
_LOCATION_NAME  n  LocationName
_NO_SIZECHECK  c  noSizeCheck
_OUTPUTFILE_POSTPREFIX  p  OutputFilePostFix
_OUTPUTFILE_PREFIX  o  OutputFilePrefix
_SHOW_TIMESTAMP  t  ShowTimestamp
_SITE_NR  s  Site
_SLEEP_HOUR  h  SleepHour
_SLEEP_MINUTE  m  SleepMinuut
_TIMEZONE  t  TimeZone

public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._OUTPUTFILE_PREFIX
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._SITE_NR
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._COUNTRY
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._TIMEZONE
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._LOCATION_ACTIVE
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._AWAKE_HOUR
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._AWAKE_MINUTE
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._NO_SIZECHECK
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._SHOW_TIMESTAMP
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._SLEEP_HOUR
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._SLEEP_MINUTE
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._EXTENTIE
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._CALC_FILENAME
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._IMAGE_SIZE
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._LOCATIE_NR
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._CAPTURE_INTERVAL_SECONDS
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._OUTPUTFILE_POSTPREFIX
public static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS._LOCATION_NAME
public char nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS.id
public final java.lang.String nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS.text
private static final nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS[] nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS.ENUM$VALUES

nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS
Sorted on: _TEXT
AwakeHour  a  _AWAKE_HOUR
AwakeMinuut  b  _AWAKE_MINUTE
CalcFileName  q  _CALC_FILENAME
CaptureIntervalSeconds  i  _CAPTURE_INTERVAL_SECONDS
Country  c  _COUNTRY
Extentie  e  _EXTENTIE
Image size  s  _IMAGE_SIZE
Locatie  l  _LOCATIE_NR
Location Active  a  _LOCATION_ACTIVE
LocationName  n  _LOCATION_NAME
OutputFilePostFix  p  _OUTPUTFILE_POSTPREFIX
OutputFilePrefix  o  _OUTPUTFILE_PREFIX
ShowTimestamp  t  _SHOW_TIMESTAMP
Site  s  _SITE_NR
SleepHour  h  _SLEEP_HOUR
SleepMinuut  m  _SLEEP_MINUTE
TimeZone  t  _TIMEZONE
noSizeCheck  c  _NO_SIZECHECK

nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS
Sorted on: _ID
a  _AWAKE_HOUR  AwakeHour
a  _LOCATION_ACTIVE  Location Active
b  _AWAKE_MINUTE  AwakeMinuut
c  _COUNTRY  Country
c  _NO_SIZECHECK  noSizeCheck
e  _EXTENTIE  Extentie
h  _SLEEP_HOUR  SleepHour
i  _CAPTURE_INTERVAL_SECONDS  CaptureIntervalSeconds
l  _LOCATIE_NR  Locatie
m  _SLEEP_MINUTE  SleepMinuut
n  _LOCATION_NAME  LocationName
o  _OUTPUTFILE_PREFIX  OutputFilePrefix
p  _OUTPUTFILE_POSTPREFIX  OutputFilePostFix
q  _CALC_FILENAME  CalcFileName
s  _IMAGE_SIZE  Image size
s  _SITE_NR  Site
t  _SHOW_TIMESTAMP  ShowTimestamp
t  _TIMEZONE  TimeZone

nl.yokoz.maxrecorder.db.dd.MaxRecorderIniDD$_FIELDS
Sorted on: _NAAM
_AWAKE_HOUR  a  AwakeHour
_AWAKE_MINUTE  b  AwakeMinuut
_CALC_FILENAME  q  CalcFileName
_CAPTURE_INTERVAL_SECONDS  i  CaptureIntervalSeconds
_COUNTRY  c  Country
_EXTENTIE  e  Extentie
_IMAGE_SIZE  s  Image size
_LOCATIE_NR  l  Locatie
_LOCATION_ACTIVE  a  Location Active
_LOCATION_NAME  n  LocationName
_NO_SIZECHECK  c  noSizeCheck
_OUTPUTFILE_POSTPREFIX  p  OutputFilePostFix
_OUTPUTFILE_PREFIX  o  OutputFilePrefix
_SHOW_TIMESTAMP  t  ShowTimestamp
_SITE_NR  s  Site
_SLEEP_HOUR  h  SleepHour
_SLEEP_MINUTE  m  SleepMinuut
_TIMEZONE  t  TimeZone

Geen opmerkingen:

Een reactie posten