Mapping enums to entities with Groovy - groovy

I have the following database table:
widget_types
------------
widget_type_id
widget_type_name
widget_type_alias
widget_type_description
This corresponds to the following Groovy entity class:
class WidgetType extends BaseLookupEntity {
Long id
String name
String alias
String description
}
In reality, WidgetType/widget_types really ought to be enums, because they are reference/lookup types with a small number of valid values:
RedWidget
SillyWidget
HappyWidget
BerserkingWidget
SausageWidget
For reasons outside the scope of this question, it is not really possible for me to OR/map the widget_types table to an enum. And so I have created a "helper enum":
enum WidgetTypeLookup {
Red,
Silly,
Happy,
Berserking,
Sausage
static WidgetTypeLookup toWidgetTypeLookup(WidgetType type) {
// TODO: ???
null
}
}
The idea here is that the JPA/OR layer will create WidgetType instances, but to be able to get real use out of them (type safety, etc.), I'd like to be able to convert them to WidgetTypeLookups:
// Inside some method...
WidgetType widgetType = getSomehowButStillNotSureWhichTypeItIs()
WidgetTypeLookup wtLookup = WidgetTypeLookup.toWidgetTypeLookup(widgetType)
switch(wtLookup) {
case Happy:
// etc...
}
So I'm struggling to find an efficient "Groovy way" of converting between the POGO type and the enum. Basically implementing the helper method. Any ideas?

I agree with the other answer that there might be better way to address your problem by improving OO design. Although I'll try to fit into your approach.
First - couldn't you just do it as follow and map the name as enum straight away?
class WidgetType extends BaseLookupEntity {
Long id
WidgetName name
String alias
String description
enum WidgetName {
Red,
Silly,
Happy,
Berserking,
Sausage
}
}
Second - the method you want to implement could be implemented like:
static WidgetTypeLookup toWidgetTypeLookup(WidgetType type) {
values().find {
it.name() == type.name
}
}
However:
the condition may need to be adjusted if names don't exactly match
you may need to handle somehow the case when there is no matching enum found
the name of the method should be rather something as fromWidgetType() then you'll have call like WidgetTypeLookup.fromWidgetType(widgetType) instead of redundant WidgetTypeLookup.toWidgetTypeLookup(widgetType)
Third - Even more groovy would be to implement custom type conversion as follows (I altered original classes names to reflect better what they are IMHO):
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
}
}
}
}
Then you can go like:
WidgetType widgetType = new WidgetTypeDetails(name: 'Red') as WidgetType

An enum is a limited number of fixed elements, unless that table have only fixed rows, Widget Red/Silly/etc should be subclasses.
You could implement the helper method inside the WidgetType class and operate specializations from an inner enum (though they can't reference the outer class)
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"
I think widget.install() is cooler and more OO (in a sense I don't need to pull the object guts to do something).
Another solution would be if WidgetType were an abstract class, and your ORM would instantiate the correct concrete type based on a specific value:
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' }
}
The fake 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)
}
}
}
Testing:
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'

Related

Groovy: Is there a way to implement multiple inheritance while using type-checking?

#groovy.transform.TypeChecked
abstract class Entity {
...
double getMass() {
...
}
...
}
#groovy.transform.TypeChecked
abstract class Location {
...
Entity[] getContent() {
...
}
...
}
#groovy.transform.TypeChecked
abstract class Container {...} //inherits, somehow, from both Location and Entity
#groovy.transform.TypeChecked
class Main {
void main() {
double x
Container c = new Chest() //Chest extends Container
Entity e = c
x = e.mass
Location l = c
x = l.content //Programmer error, should throw compile-time error
}
}
Essentially, is there a way to achieve this, without sacrificing any of the three properties outlines in main():
Direct access to fields, even virtual fields
Assigning to both super-classes
Typechecking (at compile-time)
I don't think you can do that with classes. Maybe you'd wanted traits (under discussion update: available in Groovy 2.3 and already rocking!) or, for a pure dynamic solution, #Mixin, which you'd back up with a good test suite.
My guess: #Delegate is your best friend here, but, as it stands, you can only store a Chest object in a Container type variable. So you'd need some interfaces.
Even if the superclass is not under your control, you can use groovy as operator to make it implement an interface.
First, i rewrote your classes to remove the abstract and add interfaces:
import groovy.transform.TypeChecked as TC
interface HasMass { double mass }
interface HasContent { Entity[] getContent() }
#TC class Entity implements HasMass { double mass }
#TC class Location {
Entity[] getContent() {
[new Entity(mass: 10.0), new Entity(mass: 20.0)] as Entity[]
}
}
Note i didn't added HasContent to Location, to show the usage of as.
Second, comes the Container and Chest. #Delegate is added and it auto-inherits the interfaces of the delegates:
#TC
abstract class Container {
#Delegate Location location = new Location()
#Delegate Entity entity = new Entity()
}
#TC class Chest extends Container { }
Last, it becomes type-checkable, as long as you stick to interfaces:
#TC class Mult {
static main(args) {
def x // use 'def' for flow-typing
Container c = new Chest() //Chest extends Container
HasMass e = c
x = e.mass
def l = c as HasContent
x = l.content //Programmer error, should throw compile-time error
assert c.content.collect { Entity it -> it.mass } == [10.0, 20.0]
}
}

Method aliasing in class with Groovy

I'm going to internationalize groovy API abit.
For final class (e.g. String)
String.metaClass.вСтроку = {-> this.toString() }
However, this will create additional closure. Isn't there any way to just alias method with another method?
Something like this:
String.metaClass.вСтроку = String.metaClass.&toString
You could use #Category transform like this
#Category(String) class StringInternationalization {
String вСтроку() {
this.toString()
}
int длина() {
this.length()
}
}
class ApplyMixin {
static {
String.mixin(StringInternationalization)
final helloString = "Привет мир!"
println helloString.вСтроку()
assert helloString.длина() == helloString.length()
}
}
new Main()
This will create 1 Category class for each localised class and one class to apply all mixin transformations(to register all methods.) Also should be faster, then individual closures.
More reading here: http://groovy.codehaus.org/Category+and+Mixin+transformations

Is there a way to check that class or object has a mixin in Groovy?

There is an example on Groovy's User Guide:
#Category(Vehicle) class FlyingAbility {
def fly() { "I'm the ${name} and I fly!" }
}
#Category(Vehicle) class DivingAbility {
def dive() { "I'm the ${name} and I dive!" }
}
interface Vehicle {
String getName()
}
#Mixin(DivingAbility)
class Submarine implements Vehicle {
String getName() { "Yellow Submarine" }
}
#Mixin(FlyingAbility)
class Plane implements Vehicle {
String getName() { "Concorde" }
}
#Mixin([DivingAbility, FlyingAbility])
class JamesBondVehicle implements Vehicle {
String getName() { "James Bond's vehicle" }
}
If I have an instance of JamesBondVehicle:
def vehicle = new JamesBondVechile()
How do I check that vehicle have a flying ability? Especially in case I don't know how the vehicle was created.
The following does not work:
assert vehicle instanceof FlyingAbility
The following works:
assert vehicle.respondsTo('fly')
But it's not a generic way to check the mixin presense e.g. what if I have 2 mixins that look exactly the same, but just implement stuff differently?
I don't think it's possible. I'm not an expert on Groovy, but I did a little digging and found this function in the codebase: MixinInMetaClass.mixinClassesToMetaClass
If you look through the code there, it doesn't seem to do anything to actually preserve the names of the classes bing mixed in. Instead, it just loops through all their properties and merges them into the target class if there isn't a conflict.
Based of that, it sounds like vehicle.respondsTo('fly') is as close as you're going to get.

Retrieving an Enum through a class and its descendants

I have a class that I've defined, and I have a number of child classes derived from it. The parent class has an enum (let's call it 'Barf'). Each descendant ALSO has an enum with the same name but not the same values. What I'm trying to figure out how to do is write a method in the ancestor class that gets the version of Barf for the actual class of the instantiated object. So if I create an instance of Ancestor, I'd like to have this method process the entries for Ancestor.Barf . If I create an instance of one of the child classes of Ancestor, I'd like to have the method process Childx.Barf values.
Obviously this is going to be a Reflection solution, but my reflection skills are pretty sparse. Any help?
Just for the fun of it, here is a possible approach:
public class Ancestor {
public enum Caffeine {
Tea,
Coffee
}
public void ProcessValues() {
var type = GetType();
var nestedEnums = from t in type.GetNestedTypes()
where t.IsEnum
select t;
var nestedEnum = nestedEnums.Single();
foreach(var val in Enum.GetValues(nestedEnum)) {
Console.WriteLine("Drinking {0}", val);
}
}
}
public class Descendant : Ancestor {
public new enum Caffeine {
Jolt,
RedBull
}
}
// The following prints:
// Drinking Jolt
// Drinking RedBull
Ancestor x = new Descendant();
x.ProcessValues();
Of course, you could achieve the same thing using polymorphism:
public class Ancestor {
public enum Caffeine {
Tea,
Coffee
}
protected virtual Type GetNestedEnum() {
return typeof(Ancestor.Caffeine);
}
public void ProcessValues() {
var nestedEnum = GetNestedEnum();
foreach(var val in Enum.GetValues(nestedEnum)) {
Console.WriteLine("Drinking {0}", val);
}
}
}
public class Descendant : Ancestor {
public new enum Caffeine {
Jolt,
RedBull
}
protected override Type GetNestedEnum() {
return typeof(Descendant.Caffeine);
}
}
As Justin Morgan has pointed out however, having the need for such a construct may be an indication of an underlying design issue in your code.

How to dynamically create collections of derived objects?

This question may appear to have been answered before but I have been unable to find exactly what I need. Here is my situation:
// Base class
interface IAnimal {};
public abstract class Animal : IAnimal{}
// Derived classes
interface IDog {}
public class Dog : Animal, IDog { }
interface ICat { }
public class Cat : Animal, ICat { }
interface ITiger { }
public class Tiger : Animal, ITiger { }
interface ILion { }
public class Lion : Animal, ILion { }
// Collection Classes
interface IPets { }
public class Pets
{
IDog dog = new Dog();
ICat cat = new Cat();
}
interface ICircus { }
public class Circus
{
ITiger tiger = new Tiger();
ILion lion = new Lion();
}
I would like to create the collections at run time in an generic Event class by reading in a list animals from xml that would make up the collection. What would be the correct way to accomplish this?
Thanks in advance.
This is kind of an answer to my own question. Maybe this will help others.
I chose a very generic example to illustrate my situation because I have uses for this in many places in Windows Forms, XNA and Silverlight that are all very different.
When I used the Activator, I found out that it assumes the executing assembly. My method is in a library so I had to load a different assembly. Next I had to make sure that I had the right namespace. My base class is in a library and the derived classes are in another namespace so this will require refactoring to properly create the list.
Another problem I found was that the Activator assumes a constructor with no parameters. In my test case all my derived classes are XNA game components with a parameter of type Game.
Have to do some refactoring to test out the interfaces and how the game objects are to interact.
Will be back to this list when I have something further.
Does this sort of example help? (It's from some of my code I happened to have handy.) The key point here is the use of reflection in Activator.CreateInstance(...).
public static List<dynamic> LoadChildEntities(XElement entityElt)
{
var children = new List<dynamic>();
foreach(XElement childElt in entityElt.Elements("entity"))
{
// Look up the C# type of the child entity.
string childTypename = "MyNamespace." + Convert.ToString(childElt.Attribute("type").Value);
Type childType = Type.GetType(childTypename);
if(childType != null)
{
// Construct the child entity and add it to the list.
children.Add(Activator.CreateInstance(childType, childElt));
}
else
{
throw new InvalidOperationException("No such class: " + childTypename);
}
}
return children;
}
If you want a list of IAnimal instead, it wouldn't be too tricky to change.

Resources