Transformers: more than meets the eye.
This is an unimplemented proposal for handling non-basic types in Depot in an
extensible way, instead of continuing down the road of the ByteEnum-style
hackery that we've been doing to date. The basic design is as follows:
Annotate either a field or a class with @Transform and specify the classname of
a Transformer in that annotation. For example:
public class MyRecord extends PersistentRecord {
@Transform(Transformers.CommaSeparatedString.class)
public String[] cities;
}
will cause "cities" to be combined into a single string (comma separated)
before storing in the database, and split back into a string array from the
single string when read from the database.
Alternatively, one can annotate a type:
@Transform(ByteEnumTransformer.class)
public interface ByteEnum { ... }
If Depot sees a field of non-basic type, it will look for a @Transform
annotation on the field's type (and any interfaces implemented by that type or
its parent types, which is not auto-magic). If it finds one, it will use it.
Otherwise it will fall back to what it does now (which I think is to just foist
the object off to JDBC and hope for the best).
Comments and suggestions are invited.
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Depot library - a Java relational persistence library
|
||||
// Copyright (C) 2006-2010 Michael Bayne and Pär Winzell
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.depot;
|
||||
|
||||
/**
|
||||
* Transforms a persistent record field into a format that can be read and written by the
|
||||
* underlying database. For example, one might transform an enum into a byte, short or integer. Or
|
||||
* one might transform a string array into a single string, using a separator known to be
|
||||
* appropriate for the contents.
|
||||
*
|
||||
* @see Transformers
|
||||
*/
|
||||
public interface Transformer<F,T>
|
||||
{
|
||||
/** Transforms a runtime value into a value that can be persisted. */
|
||||
T toPersistent (F value);
|
||||
|
||||
/** Transforms a persisted value into a value that can be store in a runtime field. */
|
||||
F fromPersistent (T value);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Depot library - a Java relational persistence library
|
||||
// Copyright (C) 2006-2010 Michael Bayne and Pär Winzell
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.depot;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
|
||||
import com.samskivert.depot.annotation.Column;
|
||||
|
||||
/**
|
||||
* Contains various generally useful {@link Transformer} implementations. To use a transformer, you
|
||||
* specify it via a {@link Column} annotation. For example:
|
||||
* <pre>
|
||||
* public class MyRecord extends PersistentRecord {
|
||||
* @Transform(Transformers.CommaSeparatedString.class)
|
||||
* public String[] cities;
|
||||
* }
|
||||
* </pre>
|
||||
* Because of limitations of Java's annotation system, configuration of transformers is not
|
||||
* possible (without complex machinations) and separate classes must be created for any particular
|
||||
* transformation.
|
||||
*/
|
||||
public class Transformers
|
||||
{
|
||||
/**
|
||||
* Combines the contents of a String[] column into a single string, separated by commas.
|
||||
*/
|
||||
public static class CommaSeparatedString implements Transformer<String[], String> {
|
||||
public String toPersistent (String[] value) {
|
||||
return Joiner.on(",").join(value);
|
||||
}
|
||||
public String[] fromPersistent (String value) {
|
||||
return value.split(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Depot library - a Java relational persistence library
|
||||
// Copyright (C) 2006-2010 Michael Bayne and Pär Winzell
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.depot.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import com.samskivert.depot.Transformer;
|
||||
|
||||
/**
|
||||
* Declares that the target of this annotation, either a field in a {@link PersistentRecord} or a
|
||||
* type (which will eventually be stored in a persistent record), should be transformed before
|
||||
* saving to the database and after loading from the database.
|
||||
*
|
||||
* <p> For example, one may choose to transform a particular persistent record field into a type
|
||||
* supported directly by Depot:
|
||||
*
|
||||
* <pre>
|
||||
* public class MyRecord extends PersistentRecord {
|
||||
* @Transform(Transformers.CommaSeparatedString.class)
|
||||
* public String[] cities;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* or one may opt to specify a transformation for all fields that contain a value of a particular
|
||||
* type:
|
||||
*
|
||||
* <pre>
|
||||
* @Transform(ByteEnumTransformer.class)
|
||||
* public interface ByteEnum { ... }
|
||||
* </pre>
|
||||
*
|
||||
* Note that because Depot honors @Transform annotations on any interface implemented by a type, or
|
||||
* on a type's superclass, it is possible that conflicting transformations may be specified. In
|
||||
* this case, Depot will fail with a runtime error during initialization, to indicate the problem.
|
||||
*
|
||||
* @see Transformer
|
||||
*/
|
||||
@Target(value={ElementType.TYPE, ElementType.FIELD})
|
||||
@Retention(value=RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
public @interface Transform
|
||||
{
|
||||
/**
|
||||
* Specifies a transformer to be used when persisting the target of this annotation.
|
||||
*/
|
||||
Class<? extends Transformer> value ();
|
||||
}
|
||||
Reference in New Issue
Block a user