Map --> Interface [update 30.08.2011][2]
Veröffentlicht: 17.05.2011 um 15:46 von Tomate_Salat
Aktualisiert: 19.09.2011 um 23:46 von Tomate_Salat
Aktualisiert: 19.09.2011 um 23:46 von Tomate_Salat
Update[20.09.2011]
Ab sofort wird das Projekt unter Google Code weiter laufen. Die Seite findet ihr hier
Update[30.08.2011][2]
Neben Namensänderungen (CFactory => JMapper, Pakete wurden umbenannt) ist das Projekt jetzt Modular aufgebaut. Der Wunsch nach Generics wurde ebenfalls implementiert. Zudem ist es jetzt möglich, einfach selber Module oder Plugins zu entwickeln (die bestehenden wurden in einzelne Module ausgelagert).
Was noch fehlt:
Die alte Version lasse ich mal noch zum downloaden hier stehen.
Die neueste erkennt ihr an dem Schema: jmapper_[jahr][monat][tag].jar
Kleines Beispiel der neuen Fähigkeiten des Systems:
Ausgabe:
--------------------------------------------------------------------------------------------
Ich habe mal wieder ein wenig mit Annotationen herumgespielt und wollte irgendetwas halbwegs sinnvolles mit realisieren. Dabei entstand eine kleine Factory, welche aus einer Map<Object,Object> ein verwendbares Objekt erstellt. Beispiel:
Die Ausgabe:
Die Daten sind immer aktuell und können in der Map gesetzt werden, auch wenn der Datensatz noch nicht existiert (siehe
Ein Szenario findet sich auch schnell: man möchte das andere Klassen (z.B. plugins) nur mit den bereitgestellten Werten arbeiten.
Wenn der Schlüssel(welchen ihr in der Annotation als
Leistungszusammenfassung (die grünen Einträge sind neu hinzu gekommen | die blauen wurden am selben Tag nachgereicht)
Ab sofort wird das Projekt unter Google Code weiter laufen. Die Seite findet ihr hier
Update[30.08.2011][2]
Neben Namensänderungen (CFactory => JMapper, Pakete wurden umbenannt) ist das Projekt jetzt Modular aufgebaut. Der Wunsch nach Generics wurde ebenfalls implementiert. Zudem ist es jetzt möglich, einfach selber Module oder Plugins zu entwickeln (die bestehenden wurden in einzelne Module ausgelagert).
Was noch fehlt:
- Haufenweise kommentare
- Projekt als OSGi-Bundle
- Das ganze als Open-Source-Projekt hosten
Die alte Version lasse ich mal noch zum downloaden hier stehen.
Die neueste erkennt ihr an dem Schema: jmapper_[jahr][monat][tag].jar
Kleines Beispiel der neuen Fähigkeiten des Systems:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 package de.jfruit.factory.demo; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Map; import java.util.Properties; import de.jfruit.jmapper.JMapper; import de.jfruit.jmapper.Link; import de.jfruit.jmapper.modules.MapperModule; import de.jfruit.jmapper.modules.MapperPlugin; public class PluginDemo { public static void main(String[] args) { Properties props=new Properties(); props.setProperty("test", "hallo"); JMapper.install(Version.class, MyExtension.class); Config conf=JMapper.createFromMap(props, Config.class); System.out.println("Version : " + conf.version()); System.out.println("AlphaVersion: " + conf.alphaVersion()); System.out.println("AlphaTest : " + conf.alphaTest()); System.out.println("---"); JMapper.install(Alpha.class, MyExtension.class); // <-- Sofort wirksam System.out.println("Version : " + conf.version()); System.out.println("AlphaVersion: " + conf.alphaVersion()); System.out.println("AlphaTest : " + conf.alphaTest()); } public static interface Config { @Version String version(); @Alpha @Version String alphaVersion(); @Alpha @Link(key="test") String alphaTest(); } @Retention(RetentionPolicy.RUNTIME) public static @interface Alpha {}; @Retention(RetentionPolicy.RUNTIME) public static @interface Version { String value() default "1.0"; } public static class MyExtension implements MapperModule<Version>, MapperPlugin<Alpha> { @Override public Object executeModule(Version anno, Map<Object, Object> prop, Object[] parameter, Class<?> expectedReturnType, Object worstCaseResult) { return anno.value(); } @Override public Object executePlugin(Alpha anno, Map<Object, Object> prop, Object[] parameter, Object currentValue, Object worstCaseResult) { return currentValue + "_alpha"; } } }
Ausgabe:
Code:
Version : 1.0 AlphaVersion: 1.0 AlphaTest : hallo --- Version : 1.0 AlphaVersion: 1.0_alpha AlphaTest : hallo_alpha
Ich habe mal wieder ein wenig mit Annotationen herumgespielt und wollte irgendetwas halbwegs sinnvolles mit realisieren. Dabei entstand eine kleine Factory, welche aus einer Map<Object,Object> ein verwendbares Objekt erstellt. Beispiel:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 import java.util.Properties; import de.jfruit.factory.Adapter; import de.jfruit.factory.CFactory; import de.jfruit.factory.ILinkAdapter; import de.jfruit.factory.Link; import de.jfruit.factory.ILinkParser; import de.jfruit.factory.MethodType; public class AdapterDemo { public static void main(String[] args) { Properties props=new Properties(); props.put("smode", true); props.put("user",2); MyFace face=CFactory.createFromMap(props, MyFace.class); System.out.println("SMODE: " + face.isSingleUser()); face.setCounter(12); System.out.println("Counter: " + face.counterToString()); System.out.println("User: " + face.userToString()); } } interface MyFace { // Standard @Link(key="counter") int getCounter(); @Link(key="counter",type=MethodType.SETTER) void setCounter(int i); // Erweiterung PARSER @Link(key="counter",parser=IntToStringParser.class) String counterToString(); //+ Wiederverwertbar: @Link(key="user",parser=IntToStringParser.class) String userToString(); // Erweiterung ADAPTER [Getter-only!] @Adapter(MyAdapter.class) boolean isSingleUser(); } class IntToStringParser implements ILinkParser { @Override public Object defValue() { return "NULL"; } @Override public Object parse(Object o) { return String.valueOf(o); } } class MyAdapter implements ILinkAdapter { @Override public Object key() { return "smode"; } @Override public Object defValue() { return false; } @Override public Object parse(Object o) { if(o instanceof String) { return ((String)o).equalsIgnoreCase("false") ? false : true; } return o; } }
Die Ausgabe:
Code:
SMODE: true Counter: 12 User: 2
setCounter )Ein Szenario findet sich auch schnell: man möchte das andere Klassen (z.B. plugins) nur mit den bereitgestellten Werten arbeiten.
Wenn der Schlüssel(welchen ihr in der Annotation als
key angebt) nicht in der Map gefunden wird, so wird null zurückgegeben. Der Schlüssel muss ein String-Objekt sein (wegen der Annotationen). Was auch immer ihr unter dem Schlüssel registrieren wollt kann ein x-beliebiges Objekt sein. Der Schlüssel muss zur Zeit der Erstellung auch noch nicht Existent sein. Dieser kann einfach nachträglich noch über einen Setter gesetzt werden.Leistungszusammenfassung (die grünen Einträge sind neu hinzu gekommen | die blauen wurden am selben Tag nachgereicht)
- Immer aktuelle Daten
- Zugriff nur auf festgelegte Keys möglich
- Einfache read-only implementierung
- Setter sind möglich
- Die Möglichkeit, Daten bei der Rückgabe zu Parsen(z.B. String zu Integer)
- Parser erlauben das Setzen eines Default-Wertes
- Parser sind oft wiederverwertbar
- Durch Adapter muss der
keynicht mehr zwangsläufig ein String sein - Setter können nun auch Parser verwenden.
- Plugins (MapperPlugin) und Module (MapperModule)
- Generics
- Umbenennung
- Funktionalität in Module ausgelagert
Kommentare 4
Kommentare
-
Veröffentlicht: 17.05.2011 um 16:06 von faetzminator
-
Hätte ich machen können. Ursprünglich hatte ich es mit Properties umgesetzt, entschied mich dann aber es fürMap<Object,Object>gültig zu machen. Wenn ichMap<String,Object>nutze, kann ich keine Properties mehr registriern. Aber eigentl. ist es auch egal, weil das nur für die Annotationen wichtig ist.
--------------
wo ich noch Probleme sehe, ist beim Setter. Hier führt es zu einer ClassCastException, wenn getter und setter nicht den gleichen Typ setzen/zurückliefern.Veröffentlicht: 17.05.2011 um 17:40 von Tomate_Salat
Aktualisiert: 17.05.2011 um 21:46 von Tomate_Salat -
Hier verstehe ich etwas nicht. Warum nennst du das Ding IntToStringParser und erzeugst auch Strings, aber hast als Parameter garkeine ints und return Value keine Strings. Du könntest das Interface ILinkParser generisch definieren. Dann könntest Du die richtigen Typen benutzen und nicht Object. Also z.B. so
Die Implementierende Klasse macht dann das:1 2 3 4 5 6 7
public interface ToStringParser<S,T> { public T defValue(); public T parse(S source); }
Veröffentlicht: 10.08.2011 um 23:33 von nillehammer
-
Danke für die Idee. Gibt nichts was dagegen sprechen würde, also werde ich schauen, dass ich es schnell eingebaut bekomme.
Edit Ok, ich bau das jz ein wenig mehr um: Erstmal wird CFactory in JMapper umbenannt und dann wird das ganze ein Modular (und als OSGi-Bundle). Danach will ich das mal als Open-Source-Projekt hosten.Veröffentlicht: 29.08.2011 um 08:26 von Tomate_Salat
Aktualisiert: 29.08.2011 um 22:22 von Tomate_Salat



!["Map --> Interface [update 30.08.2011][2]" bei Mister Wong speichern](http://www.java-forum.org/images/misc/bookmarksite_misterwong.gif)
!["Map --> Interface [update 30.08.2011][2]" bei YiGG.de speichern](http://www.java-forum.org/images/misc/bookmarksite_yigg.gif)
!["Map --> Interface [update 30.08.2011][2]" bei Google speichern](http://www.java-forum.org/images/misc/bookmarksite_google.gif)
!["Map --> Interface [update 30.08.2011][2]" bei del.icio.us speichern](http://www.java-forum.org/images/misc/bookmarksite_delicious.gif)

