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 |
} |