使用Groovy将枚举映射到实体

时间:2015-09-28 07:47:11

标签: groovy enums

我有以下数据库表:

widget_types
------------
widget_type_id
widget_type_name
widget_type_alias
widget_type_description

这对应于以下Groovy实体类:

class WidgetType extends BaseLookupEntity {
    Long id
    String name
    String alias
    String description
}

实际上,WidgetType / widget_types确实应该是enums,因为它们是具有少量有效值的引用/查找类型:

  • RedWidget
  • SillyWidget
  • HappyWidget
  • BerserkingWidget
  • SausageWidget

由于超出此问题范围的原因,我无法将widget_types表格或enum映射到enum WidgetTypeLookup { Red, Silly, Happy, Berserking, Sausage static WidgetTypeLookup toWidgetTypeLookup(WidgetType type) { // TODO: ??? null } } 。所以我创建了一个“helper enum”:

WidgetType

这里的想法是JPA / OR层将创建WidgetTypeLookups个实例,但为了能够真正使用它们(类型安全等),我希望能够转换他们到// Inside some method... WidgetType widgetType = getSomehowButStillNotSureWhichTypeItIs() WidgetTypeLookup wtLookup = WidgetTypeLookup.toWidgetTypeLookup(widgetType) switch(wtLookup) { case Happy: // etc... }

    internal DateTime GetContentCreatedDate()
    {
        Word.Document doc = Globals.ThisAddIn.Application.ActiveDocument;
        Office.DocumentProperties properties = (Office.DocumentProperties)doc.BuiltInDocumentProperties;
        return (DateTime)properties[Word.WdBuiltInProperty.wdPropertyTimeCreated].Value;
    }

所以我很难找到一种在POGO类型和枚举之间进行转换的有效“Groovy方式”。基本上实现了辅助方法。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

我同意另一个答案,即通过改进面向对象设计可能有更好的方法来解决您的问题。虽然我会尽力适应你的方法。

首先 - 您不能按照以下方式执行此操作并立即将名称映射为枚举吗?

class WidgetType extends BaseLookupEntity {
    Long id
    WidgetName name
    String alias
    String description

    enum WidgetName {
        Red,
        Silly,
        Happy,
        Berserking,
        Sausage
    }
}

第二 - 您要实施的方法可以实现为:

static WidgetTypeLookup toWidgetTypeLookup(WidgetType type) {
    values().find {
        it.name() == type.name
    }
}

然而:

  • 如果名称不完全匹配,则可能需要调整条件
  • 如果找不到匹配的枚举
  • ,您可能需要处理某种情况
  • 该方法的名称应该是fromWidgetType(),然后您可以调用WidgetTypeLookup.fromWidgetType(widgetType)而不是冗余WidgetTypeLookup.toWidgetTypeLookup(widgetType)

第三次 - 更加常规的是实现自定义类型转换,如下所示(我更改了原始类名称以更好地反映它们是什么样的恕我直言):

enum WidgetType {
    Red,
    Silly,
    Happy,
    Berserking,
    Sausage
}

class WidgetTypeDetails {
    Long id
    String name
    String alias
    String description

    Object asType(Class clazz) {
        if (clazz == WidgetType) {
            WidgetType.values().find {
                it.name() == this.name
            }
        }
    }
}

然后你可以像:

WidgetType widgetType = new WidgetTypeDetails(name: 'Red') as WidgetType

答案 1 :(得分:0)

枚举是有限数量的固定元素,除非该表只有固定行,Widget Red/Silly/etc应该是子类。

你可以在WidgetType类中实现helper方法,并从内部枚举中操作特化(尽管它们不能引用外部类)

class WidgetType {
    Long id
    String name
    String alias
    String description

    enum Type {
        RED, 
        SAUSAGE {
            def install(container) {
                "installing elongated component into $container"
            }
        }, 
        SILLY, 
        HAPPY, 
        BERSERKING

        def install(container) {
            "installed ${name()} into $container"
        }
    }

    Type getType() {
        Type.values().find { it.name() == name }
    }
}

red = new WidgetType(name: 'RED')

assert red.type.install("main container") == 
        "installed RED into main container"

sausage = new WidgetType(name: 'SAUSAGE')

assert sausage.type.install("display") == 
        "installing elongated component into display"

我认为widget.install()更酷,更OO(从某种意义上说,我不需要拉扯对象的胆量来做某事)。

另一种解决方案是,如果WidgetType是一个抽象类,并且您的ORM将根据特定值实例化正确的具体类型:

abstract class WidgetType {
    Long id
    String name
    String alias
    String description

    abstract install(container)

    enum Type {
        RED(RedWidget), 
        SAUSAGE(SausageWidget), 
    }

    static WidgetType from(type, properties) {
        Type.values().find { it.name() == type }
            .clazz
            .newInstance(properties: properties)
    }
}

class RedWidget extends WidgetType {
    def install(container) { 'red installing into $container' }
}

class SausageWidget extends WidgetType {
    def install(container) { 'elongated component installing into $container' }
}

假的ORM:

class ORM {
    def container = [
        (1) : [
            id: 1, 
            name: 'RED', 
            alias: 'my red alias',
            description: 'this art red' ],
        (2) : [
            id: 2, 
            name: 'SAUSAGE', 
            alias: 'long component', 
            description: 'sausage component' ] 
    ]

    def get(id) {
        container[it].with {
            WidgetType.from(it.name, id)
        }
    }
}

测试:

red = new ORM().get(1)
assert red.install('main') == 
        'red installing into main'

sausage = new ORM().get(2)
assert sausage.install('display') == 
        'elongated component installing into display'