Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libTools / src / org / gvsig / tools / persistence / xml / XMLPersistentStateWriter.java @ 30619

History | View | Annotate | Download (11 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2009 IVER T.I   {{Task}}
26
 */
27

    
28
/**
29
 *
30
 */
31
package org.gvsig.tools.persistence.xml;
32

    
33
import java.io.OutputStream;
34
import java.io.OutputStreamWriter;
35
import java.io.PrintWriter;
36
import java.lang.reflect.Method;
37
import java.text.MessageFormat;
38
import java.util.Date;
39
import java.util.Iterator;
40
import java.util.List;
41
import java.util.Map;
42
import java.util.Set;
43
import java.util.Map.Entry;
44
import java.util.regex.Pattern;
45

    
46
import org.gvsig.tools.persistence.PersistenceException;
47
import org.gvsig.tools.persistence.PersistenceTypeNotSupportedException;
48
import org.gvsig.tools.persistence.impl.ImplementationPersistentState;
49
import org.gvsig.tools.persistence.impl.ObjectReference;
50
import org.gvsig.tools.persistence.impl.PersistentContext;
51

    
52
/**
53
 * @author jmvivo
54
 *
55
 */
56
public class XMLPersistentStateWriter implements XMLPersistentConstants {
57

    
58
        private XMLPersistenceManager manager;
59
        private PrintWriter print;
60
        private static Method getCharSetMethod = null;
61
        private static Method getCharSetNameMethod = null;
62
        private static boolean useCsMap = false;
63
        private static boolean useDomains = false;
64

    
65
        private final static Pattern DOT_PATTERN = Pattern.compile("[.]");
66

    
67
        public XMLPersistentStateWriter(XMLPersistenceManager persistenceManager) {
68
                this.manager = persistenceManager;
69
        }
70

    
71
        public void write(ImplementationPersistentState state, OutputStream out)
72
                        throws PersistenceException {
73
                write(state, out, null);
74
        }
75

    
76
        public void write(ImplementationPersistentState state, OutputStream out,
77
                        Map domains)
78
                        throws PersistenceException {
79
                ImplementationPersistentState root = state;
80
                String rootId = root.getId().toString();
81
                PersistentContext context = state.getContext();
82
                OutputStreamWriter outWrite = new OutputStreamWriter(out);
83
                print = new PrintWriter(out);
84

    
85
                // XML header (<?xml ....?>)
86
                print.println(MessageFormat.format(XML_HEADER,
87
                                new String[] { getCharset(outWrite.getEncoding()) }));
88

    
89
                // Prepare schema
90
                String rootAttributes = "";
91
                if (domains != null && domains.size() > 0) {
92
                        useDomains = true;
93
                        StringBuffer buffRootAttr = new StringBuffer();
94

    
95
                        buffRootAttr.append('\n');
96
                        buffRootAttr.append(MessageFormat.format(
97
                                        DOMAIN_NAME_ATTRIBUTE_VALUE, new Object[] {
98
                                                        BASE_DOMIAN_NAME, BASE_DOMIAN_URL }));
99
                        Iterator iter = domains.entrySet().iterator();
100
                        Entry entry;
101
                        while (iter.hasNext()) {
102
                                entry = (Entry) iter.next();
103
                                buffRootAttr.append('\n');
104
                                buffRootAttr.append(MessageFormat.format(DOMAIN_NAME_ATTRIBUTE_VALUE,
105
                                                new Object[] { entry.getKey(), entry.getValue() }));
106
                        }
107
                        iter = domains.entrySet().iterator();
108
                        StringBuffer buffSchemas = new StringBuffer();
109

    
110
                        buffSchemas.append('\n');
111
                        buffSchemas.append(MessageFormat.format(SCHEMA_DEFINITON_VALUE,
112
                                        new Object[] { BASE_DOMIAN_NAME, BASE_DOMIAN_URL }));
113
                        while (iter.hasNext()) {
114
                                entry = (Entry) iter.next();
115
                                buffSchemas.append('\n');
116
                                buffSchemas.append(MessageFormat.format(SCHEMA_DEFINITON_VALUE,
117
                                                new Object[] { entry.getValue(), entry.getKey() }));
118
                        }
119
                        buffRootAttr.append('\n');
120
                        buffRootAttr.append(MessageFormat.format(DEFAULT_SCHEMA_ATTRIBUTE_VALUE,
121
                                        new Object[] { buffSchemas.toString() }));
122
                        rootAttributes = buffRootAttr.toString();
123
                }
124

    
125
                // Root tag:
126
//                if (useDomains) {
127
//                        print.println(MessageFormat.format(ROOT_VALUE, new Object[] {
128
//                                        BASE_DOMIAN_NAME + ":", rootAttributes }));
129
//                } else {
130
                        print.println(MessageFormat.format(ROOT_VALUE,
131
                                        new Object[] { "",
132
                                        rootAttributes }));
133
//                }
134

    
135
                // Version
136
                print.println(MessageFormat.format(VERSION_VALUE,
137
                                new Object[] { manager.version() }));
138

    
139
                // add root state id
140
                print.println(MessageFormat.format(ROOTSTATE_VALUE,
141
                                new String[] { rootId }));
142

    
143
                ImplementationPersistentState curState;
144
                Iterator itStates = context.statesIterator();
145

    
146
                // States tag:
147
                print.println(STATES_START);
148

    
149
                // iter all states
150
                while (itStates.hasNext()) {
151
                        curState = (ImplementationPersistentState) itStates.next();
152
                        writeState(curState);
153

    
154
                }
155
                // States end:
156
                print.println(STATES_END);
157

    
158
                // Root end:
159
//                if (useDomains) {
160
//                        print.println(MessageFormat.format(ROOT_END_VALUE,
161
//                                        new Object[] { BASE_DOMIAN_NAME + ":" }));
162
//                } else {
163
                        print.println(MessageFormat.format(ROOT_END_VALUE,
164
                                        new Object[] { "" }));
165
//                }
166

    
167
                print.flush();
168

    
169
        }
170

    
171
        private void writeState(ImplementationPersistentState curState)
172
                        throws PersistenceException {
173
                Iterator itNames;
174
                String name;
175
                Object value;
176

    
177
                itNames = curState.getNames();
178
                String theClassName = curState.getTheClassName();
179
                String domainName = "";
180
                if (useDomains) {
181
                        domainName = manager.getDomainName(theClassName) + ":";
182
                }
183

    
184
                // add state start
185
                print.println(MessageFormat.format(STATE_START, new Object[] {
186
                                domainName, theClassName, curState.getId() }));
187

    
188
                boolean useNameAsTag;
189
                String format, type;
190
                StringBuffer strb;
191
                // iter all property names
192
                while (itNames.hasNext()) {
193
                        name = (String) itNames.next();
194
                        value = curState.getInternal(name);
195
                        strb = new StringBuffer();
196
                        type = transformValue(value, strb);
197

    
198
                        useNameAsTag = VALID_TAG_PATTERN.matcher(name).matches();
199

    
200
                        if (useNameAsTag) {
201
                                format = VALUE_ITEM;
202
                        } else {
203
                                format = VALUE_ITEM_GENERIC;
204
                        }
205

    
206
                        print.println(MessageFormat.format(format, new String[] { name,
207
                                        type, strb.toString() }));
208

    
209
                }
210

    
211
                // add state end
212
                print.println(MessageFormat.format(STATE_END, new Object[] {
213
                                domainName, theClassName, curState.getId() }));
214

    
215
        }
216

    
217
        private String transformValue(Object value, StringBuffer strb)
218
                        throws PersistenceTypeNotSupportedException {
219
                if (value instanceof String) {
220
                        return transformValue((String) value, strb);
221
                } else if (value instanceof Number) {
222
                        return transformValue((Number) value, strb);
223
                } else if (value instanceof ObjectReference) {
224
                        return transformValue((ObjectReference) value, strb);
225
                } else if (value instanceof List) {
226
                        return transformValue((List) value, strb);
227
                } else if (value instanceof Set) {
228
                        return transformValue((Set) value, strb);
229
                } else if (value instanceof Map) {
230
                        return transformValue((Map) value, strb);
231
                } else if (value instanceof Boolean) {
232
                        return transformValue((Boolean) value, strb);
233
                } else if (value instanceof Date) {
234
                        return transformValue((Date) value, strb);
235
                } else if (value == null) {
236
                        return transformNullValue(strb);
237
                } else {
238
                        throw new PersistenceTypeNotSupportedException(value.getClass());
239
                }
240
        }
241

    
242
        private String transformValue(String value, StringBuffer strb) {
243
                boolean cdata = false;
244
                if (!VALID_VALUE_PATTERN.matcher(value).matches()) {
245
                        cdata = true;
246
                        strb.append(CDATA_START);
247
                }
248

    
249
                strb.append(value);
250

    
251
                if (cdata) {
252
                        strb.append(CDATA_END);
253
                }
254

    
255
                return TYPE_STRING;
256
        }
257

    
258
        private String transformNullValue(StringBuffer strb) {
259
                return TYPE_NULL;
260
        }
261

    
262
        private String transformValue(Number value, StringBuffer strb) {
263
                strb.append(value);
264
                String[] classname = split(value.getClass().getName(), DOT_PATTERN);
265
                return classname[classname.length - 1];
266
        }
267

    
268
        private String[] split(String txt, String pattern) {
269
                return Pattern.compile(pattern).split(txt, 0);
270
        }
271

    
272
        private String[] split(String txt, Pattern pattern) {
273
                return pattern.split(txt, 0);
274
        }
275

    
276
        private String transformValue(Boolean value, StringBuffer strb) {
277
                strb.append(value);
278
                return TYPE_BOOLEAN;
279
        }
280

    
281
        private String transformValue(Date value, StringBuffer strb) {
282
                strb.append(value.getTime());
283
                return TYPE_DATE;
284
        }
285

    
286
        private String transformValue(ObjectReference value, StringBuffer strb) {
287
                strb.append(MessageFormat.format(REFERENCE_VALUE, new Object[] { value
288
                                .getId() }));
289
                return TYPE_REFERENCE;
290
        }
291

    
292
        private String transformValue(List value, StringBuffer strb)
293
                        throws PersistenceTypeNotSupportedException {
294
                Iterator iter = value.iterator();
295
                String type;
296
                StringBuffer itemStrb;
297
                while (iter.hasNext()) {
298
                        itemStrb = new StringBuffer();
299
                        type = transformValue(iter.next(), itemStrb);
300
                        strb.append(MessageFormat.format(LISTITEM_VALUE, new String[] {
301
                                        type, itemStrb.toString() }));
302
                        strb.append('\n');
303
                }
304

    
305
                return "List";
306
        }
307

    
308
        private String transformValue(Set value, StringBuffer strb)
309
                        throws PersistenceTypeNotSupportedException {
310
                Iterator iter = value.iterator();
311
                String type;
312
                StringBuffer itemStrb;
313
                while (iter.hasNext()) {
314
                        itemStrb = new StringBuffer();
315
                        type = transformValue(iter.next(), itemStrb);
316
                        strb.append(MessageFormat.format(SETITEM_VALUE, new String[] {
317
                                        type, itemStrb.toString() }));
318
                }
319

    
320
                return "Set";
321
        }
322

    
323
        private String transformValue(Map value, StringBuffer strb)
324
                        throws PersistenceTypeNotSupportedException {
325
                Iterator iter = value.entrySet().iterator();
326
                Entry entry;
327
                String keyType, valueType;
328
                StringBuffer valueStrb, keyStrb;
329
                while (iter.hasNext()) {
330
                        entry = (Entry) iter.next();
331
                        // transform key
332
                        keyStrb = new StringBuffer();
333
                        keyType = transformValue(entry.getKey(), keyStrb);
334
                        // transform value
335
                        valueStrb = new StringBuffer();
336
                        valueType = transformValue(entry.getValue(), valueStrb);
337

    
338
                        strb.append(MessageFormat.format(MAPITEM_VALUE, new String[] {
339
                                        keyType, keyStrb.toString(), valueType,
340
                                        valueStrb.toString() }));
341
                }
342

    
343
                return "Map";
344
        }
345

    
346
        private String getCharsetByNio(String csName) {
347
                Object charSet;
348
                if (getCharSetNameMethod == null) {
349
                        Class charsetClass = null;
350
                        try {
351
                                charsetClass = Class.forName("java.nio.charset.Charset");
352
                        } catch (ClassNotFoundException e) {
353
                                useCsMap = true;
354
                                return null;
355
                        }
356
                        try {
357
                                getCharSetMethod = charsetClass.getMethod("forName",
358
                                                new Class[] { String.class });
359
                        } catch (Exception e) {
360
                                useCsMap = true;
361
                                return null;
362
                        }
363
                        try {
364
                                getCharSetNameMethod = charsetClass.getMethod("displayName",
365
                                                new Class[] {});
366
                        } catch (Exception e) {
367
                                useCsMap = true;
368
                                return null;
369
                        }
370

    
371
                }
372
                try {
373
                        charSet = getCharSetMethod.invoke(null, new Object[] { csName });
374
                } catch (Exception e) {
375
                        useCsMap = true;
376
                        return null;
377
                }
378

    
379
                try {
380
                        return (String) getCharSetNameMethod.invoke(charSet,
381
                                        new Object[] {});
382
                } catch (Exception e) {
383
                        useCsMap = true;
384
                        return null;
385
                }
386
        }
387

    
388
        private String getCharset(String csName) {
389
                if (!useCsMap) {
390
                        String name = this.getCharsetByNio(csName);
391
                        if (name != null) {
392
                                return name;
393
                        }
394
                }
395
                return (String) ChasetMap.getMap().get(csName);
396
        }
397
}