田源
2025-01-15 78fa1f005a9ec2581611e53d7eba8efeacb4df6e
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
package com.vci.rmip.workflow.client.editor.code;
 
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
 
import com.mxgraph.model.mxGraphModel.mxCollapseChange;
import com.mxgraph.model.mxGraphModel.mxGeometryChange;
import com.mxgraph.model.mxGraphModel.mxStyleChange;
import com.mxgraph.model.mxGraphModel.mxValueChange;
import com.mxgraph.model.mxGraphModel.mxVisibleChange;
 
public class GraphCodecRegistry {
 
    /**
     * Maps from constructor names to codecs.
     */
    protected static Hashtable<String, GraphObjectCodec> codecs = new Hashtable<String, GraphObjectCodec>();
 
    /**
     * Maps from classnames to codecnames.
     */
    protected static Hashtable<String, String> aliases = new Hashtable<String, String>();
 
    /**
     * Holds the list of known packages. Packages are used to prefix short
     * class names (eg. mxCell) in XML markup.
     */
    protected static List<String> packages = new ArrayList<String>();
 
    // Registers the known codecs and package names
    static
    {
        addPackage("com.mxgraph");
        addPackage("com.mxgraph.util");
        addPackage("com.mxgraph.model");
        addPackage("com.mxgraph.view");
        addPackage("java.lang");
        addPackage("java.util");
 
        register(new GraphObjectCodec(new ArrayList<Object>()));
        register(new GraphModelCodec());
        register(new GraphCellCodec());
        register(new GraphStylesheetCodec());
 
        register(new GraphRootChangeCodec());
        register(new GraphChildChangeCodec());
        register(new GraphTerminalChangeCodec());
        register(new GraphGenericChangeCodec(new mxValueChange(), "value"));
        register(new GraphGenericChangeCodec(new mxStyleChange(), "style"));
        register(new GraphGenericChangeCodec(new mxGeometryChange(), "geometry"));
        register(new GraphGenericChangeCodec(new mxCollapseChange(), "collapsed"));
        register(new GraphGenericChangeCodec(new mxVisibleChange(), "visible"));
    }
 
    /**
     * Registers a new codec and associates the name of the template constructor
     * in the codec with the codec object. Automatically creates an alias if the
     * codename and the classname are not equal.
     */
    public static GraphObjectCodec register(GraphObjectCodec codec)
    {
        if (codec != null)
        {
            String name = codec.getName();
            codecs.put(name, codec);
 
            String classname = getName(codec.getTemplate());
 
            if (!classname.equals(name))
            {
                addAlias(classname, name);
            }
        }
 
        return codec;
    }
 
    /**
     * Adds an alias for mapping a classname to a codecname.
     */
    public static void addAlias(String classname, String codecname)
    {
        aliases.put(classname, codecname);
    }
 
    /**
     * Returns a codec that handles the given object, which can be an object
     * instance or an XML node.
     * 
     * @param name Java class name.
     */
    public static GraphObjectCodec getCodec(String name)
    {
        String tmp = aliases.get(name);
 
        if (tmp != null)
        {
            name = tmp;
        }
 
        GraphObjectCodec codec = codecs.get(name);
 
        // Registers a new default codec for the given name
        // if no codec has been previously defined.
        if (codec == null)
        {
            Object instance = getInstanceForName(name);
 
            if (instance != null)
            {
                try
                {
                    codec = new GraphObjectCodec(instance);
                    register(codec);
                }
                catch (Exception e)
                {
                    // ignore
                }
            }
        }
 
        return codec;
    }
 
    /**
     * Adds the given package name to the list of known package names.
     * 
     * @param packagename Name of the package to be added.
     */
    public static void addPackage(String packagename)
    {
        packages.add(packagename);
    }
 
    /**
     * Creates and returns a new instance for the given class name.
     * 
     * @param name Name of the class to be instantiated.
     * @return Returns a new instance of the given class.
     */
    public static Object getInstanceForName(String name)
    {
        Class<?> clazz = getClassForName(name);
 
        if (clazz != null)
        {
            if (clazz.isEnum())
            {
                // For an enum, use the first constant as the default instance
                return clazz.getEnumConstants()[0];
            }
            else
            {
                try
                {
                    return clazz.newInstance();
                }
                catch (Exception e)
                {
                    // ignore
                }
            }
        }
 
        return null;
    }
 
    /**
     * Returns a class that corresponds to the given name.
     * 
     * @param name
     * @return Returns the class for the given name.
     */
    public static Class<?> getClassForName(String name)
    {
        try
        {
            return Class.forName(name);
        }
        catch (Exception e)
        {
            // ignore
        }
 
        for (int i = 0; i < packages.size(); i++)
        {
            try
            {
                String s = packages.get(i);
 
                return Class.forName(s + "." + name);
            }
            catch (Exception e)
            {
                // ignore
            }
        }
 
        return null;
    }
 
    /**
     * Returns the name that identifies the codec associated
     * with the given instance..
     *
     * The I/O system uses unqualified classnames, eg. for a
     * <code>com.mxgraph.model.mxCell</code> this returns
     * <code>mxCell</code>.
     * 
     * @param instance Instance whose node name should be returned.
     * @return Returns a string that identifies the codec.
     */
    public static String getName(Object instance)
    {
        Class<? extends Object> type = instance.getClass();
 
        if (type.isArray() || Collection.class.isAssignableFrom(type)
                || Map.class.isAssignableFrom(type))
        {
            return "Array";
        }
        else
        {
            if (packages.contains(type.getPackage().getName()))
            {
                return type.getSimpleName();
            }
            else
            {
                return type.getName();
            }
        }
    }
 
}