Frage

Ich pflege ein großes Dokumentarchiv und verwende häufig Bitfelder, um den Status meiner Dokumente während der Verarbeitung oder bei der Validierung aufzuzeichnen. Mein Legacy -Code verwendet lediglich statische Int -Konstanten wie:

static int DOCUMENT_STATUS_NO_STATE = 0
static int DOCUMENT_STATUS_OK = 1
static int DOCUMENT_STATUS_NO_TIF_FILE = 2
static int DOCUMENT_STATUS_NO_PDF_FILE = 4

Dies macht es ziemlich einfach, dem Status ein Dokument anzuzeigen, indem es die entsprechenden Flags festlegt. Zum Beispiel:

status = DOCUMENT_STATUS_NO_TIF_FILE | DOCUMENT_STATUS_NO_PDF_FILE;

Da der Ansatz der Verwendung statischer Konstanten eine schlechte Praxis ist und ich den Code verbessern möchte, wollte ich Enums verwenden, um dasselbe zu erreichen. Es gibt einige Anforderungen, von denen eines von ihnen die Notwendigkeit ist, den Status als numerische Typ in eine Datenbank zu speichern. Daher müssen die Aufzählungskonstanten in einen numerischen Wert umgewandelt werden. Unten ist mein erster Ansatz und ich frage mich, ob dies der richtige Weg ist.

class DocumentStatus{

    public enum StatusFlag {

        DOCUMENT_STATUS_NOT_DEFINED(1<<0),
        DOCUMENT_STATUS_OK(1<<1), 
        DOCUMENT_STATUS_MISSING_TID_DIR(1<<2),
        DOCUMENT_STATUS_MISSING_TIF_FILE(1<<3),
        DOCUMENT_STATUS_MISSING_PDF_FILE(1<<4),
        DOCUMENT_STATUS_MISSING_OCR_FILE(1<<5),
        DOCUMENT_STATUS_PAGE_COUNT_TIF(1<<6),
        DOCUMENT_STATUS_PAGE_COUNT_PDF(1<<7),
        DOCUMENT_STATUS_UNAVAILABLE(1<<8);


        private final long statusFlagValue;

        StatusFlag(long statusFlagValue) {
            this.statusFlagValue = statusFlagValue;
        }

        public long getStatusFlagValue(){
            return statusFlagValue;
        } 

       }


    /**
     * Translates a numeric status code into a Set of StatusFlag enums
     * @param numeric statusValue 
     * @return EnumSet representing a documents status
     */
    public EnumSet<StatusFlag> getStatusFlags(long statusValue) {
        EnumSet statusFlags = EnumSet.noneOf(StatusFlag.class);
        StatusFlag.each { statusFlag -> 
            long flagValue = statusFlag.statusFlagValue
            if ( (flagValue&statusValue ) == flagValue ) {
               statusFlags.add(statusFlag);
            }
        }
        return statusFlags;
    }


    /**
     * Translates a set of StatusFlag enums into a numeric status code
     * @param Set if statusFlags
     * @return numeric representation of the document status 
     */
    public long getStatusValue(Set<StatusFlag> flags) {
        long value=0;
        flags.each { statusFlag -> 
            value|=statusFlag.getStatusFlagValue() 
        }
        return value;
    }

     public static void main(String[] args) {

        DocumentStatus ds = new DocumentStatus();
        Set statusFlags = EnumSet.of(
            StatusFlag.DOCUMENT_STATUS_OK,
            StatusFlag.DOCUMENT_STATUS_UNAVAILABLE);

        assert ds.getStatusValue( statusFlags )==258 // 0000.0001|0000.0010

        long numericStatusCode = 56;
        statusFlags = ds.getStatusFlags(numericStatusCode);

        assert !statusFlags.contains(StatusFlag.DOCUMENT_STATUS_OK);
        assert statusFlags.contains(StatusFlag.DOCUMENT_STATUS_MISSING_TIF_FILE);
        assert statusFlags.contains(StatusFlag.DOCUMENT_STATUS_MISSING_PDF_FILE);
        assert statusFlags.contains(StatusFlag.DOCUMENT_STATUS_MISSING_OCR_FILE);

    }

}
War es hilfreich?

Lösung

Ihr Ansatz ist genau der Weg, dies zu tun.

Andere Tipps

Anstatt Konstruktorparameter zu definieren, können Sie einfach das interne verwenden ordinal() Wert, um dies zu berechnen.

public enum StatusFlag {

    DOCUMENT_STATUS_NOT_DEFINED,
    DOCUMENT_STATUS_OK, 
    DOCUMENT_STATUS_MISSING_TID_DIR,
    DOCUMENT_STATUS_MISSING_TIF_FILE,
    DOCUMENT_STATUS_MISSING_PDF_FILE,
    DOCUMENT_STATUS_MISSING_OCR_FILE,
    DOCUMENT_STATUS_PAGE_COUNT_TIF,
    DOCUMENT_STATUS_PAGE_COUNT_PDF,
    DOCUMENT_STATUS_UNAVAILABLE;


    public long getStatusFlagValue(){
        return 1 << this.ordinal();
    } 

}

Bitte beachten Sie, dass Sie sich jetzt nicht an das Neubestehen, Einfügen (außer am Ende) oder das Löschen von Einträgen enthalten sollten, da sich die Flag -Werte ansonsten ändern, und die Bedeutung Ihres Datenbankinhalts ändert sich.

Ein etwas besserer Weg wäre, das Ergebnis von zu speichern 1 << this.ordinal() in einem Feld, wenn die Enumwerte konstruiert werden. Auf diese Weise müssen Sie nicht jeden Wert manuell angeben, und das Flag wird nur einmal berechnet.

public enum StatusFlag {

  DOCUMENT_STATUS_NOT_DEFINED,
  DOCUMENT_STATUS_OK, 
  DOCUMENT_STATUS_MISSING_TID_DIR,
  DOCUMENT_STATUS_MISSING_TIF_FILE,
  DOCUMENT_STATUS_MISSING_PDF_FILE,
  DOCUMENT_STATUS_MISSING_OCR_FILE,
  DOCUMENT_STATUS_PAGE_COUNT_TIF,
  DOCUMENT_STATUS_PAGE_COUNT_PDF,
  DOCUMENT_STATUS_UNAVAILABLE;

  public final int flag;

  StatusFlag() { 
    this.flag = 1 << this.ordinal();
  } 
}

Bearbeiten: Es könnte nützlich sein, auch die ISFlagset -Methode zu haben.

Geben Sie Ihren Enum -Werten nicht an. Benutze ein EnumSet sie zu kombinieren und zu verwenden Enum.ordinal() beim Bestehen, um zu/von einer einzelnen Ganzzahl umzuwandeln. Sie könnten auch finden Class.getEnumConstants() Nützlich, wenn Sie den Satz aus der Ganzzahl rekonstruieren.

Ich habe eine vollständige Bibliothek für dieses Problem gemacht:http://claude-martin.ch/enumbitset/

Das Hauptziel war das Speichern von Sets von Enumentypen in Bitfields. Es unterstützt aber auch andere Typen.

Damit benötigen Sie keine zusätzlichen Methoden wie "getStatusflags ()". Es kann auf jedem vorhandenen Enum -Typ verwendet werden, indem Sie einfach die Schnittstelle hinzufügen Enumbitsethelper (Es wird wie ein "Merkmal" verwendet). Jede Enum -Konstante kann dann einen "Enumbitset" erstellen, der alle Methoden von Javas Enumset und Bitset enthält. Dann können Sie mit diesen Sätzen von Enum -Konstanten arbeiten und sie in Bitfield -Werte umwandeln.

Es unterstützt viele Formate wie Biginteger und lange, um den Wert einfach in ein Stück Feld zu speichern. Beachten Sie jedoch, dass dies nur mit Java Version 8 und neuer funktioniert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top