java-forum.org - Java programmieren aus Leidenschaft
Java 6 Einstieg und professioneller Einsatz
Alter Preis: 34,90 EUR
Jetzt: 0,00 EUR

zzgl. Versandkosten

Zurück   java-forum.org - Java programmieren aus Leidenschaft > Blogs > Tomate_Salat

Bewerten

Map --> Interface [update 30.08.2011][2]

"Map --> Interface [update 30.08.2011][2]" bei Mister Wong speichern "Map --> Interface [update 30.08.2011][2]" bei YiGG.de speichern "Map --> Interface [update 30.08.2011][2]" bei Google speichern "Map --> Interface [update 30.08.2011][2]" bei del.icio.us speichern
Veröffentlicht: 17.05.2011 um 15: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:
  • 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:
Java Code: Quelltext in neuem Fenster öffnen
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:
Java Code: Quelltext in neuem Fenster öffnen
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
Die Daten sind immer aktuell und können in der Map gesetzt werden, auch wenn der Datensatz noch nicht existiert (siehe 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 key nicht 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
Angehängte Dateien
Dateityp: zip factory-20110601[1].zip (4,4 KB, 4x aufgerufen)
Kategorie: Code-Schnipsel
Hits 1662 Kommentare 4
« Zurück     Startseite des Blogs     Nächste »
Kommentare 4

Kommentare

  1. Alter Kommentar
    Benutzerbild von faetzminator
    Und wieso ist es dann eine Map<Object, Object> und nicht wenigstens Map<String, Object> ? Die Idee ist nicht schlecht, kann aber IMHO schnell zu ClassCastExceptions führen.
    permalink
    Veröffentlicht: 17.05.2011 um 16:06 von faetzminator faetzminator ist offline
  2. Alter Kommentar
    Benutzerbild von Tomate_Salat
    Hätte ich machen können. Ursprünglich hatte ich es mit Properties umgesetzt, entschied mich dann aber es für Map<Object,Object> gültig zu machen. Wenn ich Map<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.
    permalink
    Veröffentlicht: 17.05.2011 um 17:40 von Tomate_Salat Tomate_Salat ist offline
    Aktualisiert: 17.05.2011 um 21:46 von Tomate_Salat
  3. Alter Kommentar
    Java Code: Quelltext in neuem Fenster öffnen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    class IntToStringParser
        implements ILinkParser
    {
     
        @Override
        public Object defValue() 
        {
            return "NULL";
        }
     
        @Override
        public Object parse(Object o)
        {
            return String.valueOf(o);
        }
       
    }
    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
    Java Code: Quelltext in neuem Fenster öffnen
    1
    2
    3
    4
    5
    6
    7
    
    public interface ToStringParser<S,T>
    {
     
        public T defValue();
     
        public T parse(S source);  
    }
    Die Implementierende Klasse macht dann das:
    Java Code: Quelltext in neuem Fenster öffnen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    class IntToStringParser
        implements ILinkParser<Integer,String>
    {
     
        @Override
        public String defValue() 
        {
            return "NULL";
        }
     
        @Override
        public String parse(Integer source)
        {
            return String.valueOf(source);
            // Oder ein Numberformat, oder einfac toString...
        }
       
    }
    permalink
    Veröffentlicht: 10.08.2011 um 23:33 von nillehammer nillehammer ist offline
  4. Alter Kommentar
    Benutzerbild von Tomate_Salat
    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.
    permalink
    Veröffentlicht: 29.08.2011 um 08:26 von Tomate_Salat Tomate_Salat ist offline
    Aktualisiert: 29.08.2011 um 22:22 von Tomate_Salat
 

Alle Zeitangaben in WEZ +1. Es ist jetzt 22:24 Uhr.


Powered by vBulletin® Version 3.8.6 (Deutsch)
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.2
Thanks for Smilies by smilies.4-user.de