Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.xml2db / org.gvsig.xml2db.lib / org.gvsig.xml2db.lib.impl / src / main / java / org / gvsig / xml2db / lib / impl / CopyXML2dbImpl.java @ 47606

History | View | Annotate | Download (17.4 KB)

1
package org.gvsig.xml2db.lib.impl;
2

    
3
import java.io.File;
4
import java.io.InputStream;
5
import java.nio.charset.Charset;
6
import java.util.ArrayList;
7
import java.util.HashMap;
8
import java.util.List;
9
import java.util.Map;
10
import javax.xml.parsers.SAXParser;
11
import javax.xml.parsers.SAXParserFactory;
12
import org.apache.commons.io.FilenameUtils;
13
import org.apache.commons.lang3.StringUtils;
14
import org.apache.commons.lang3.mutable.MutableInt;
15
import org.gvsig.fmap.dal.DALLocator;
16
import org.gvsig.fmap.dal.DataManager;
17
import org.gvsig.fmap.dal.DataStoreParameters;
18
import org.gvsig.fmap.dal.DataTransaction;
19
import org.gvsig.fmap.dal.feature.EditableFeature;
20
import org.gvsig.fmap.dal.feature.Feature;
21
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
22
import org.gvsig.fmap.dal.feature.FeatureQuery;
23
import org.gvsig.fmap.dal.feature.FeatureStore;
24
import org.gvsig.fmap.dal.feature.FeatureType;
25
import org.gvsig.fmap.dal.feature.ForeingKey;
26
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
27
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
28
import org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorer;
29
import org.gvsig.tools.ToolsLocator;
30
import org.gvsig.tools.dispose.DisposeUtils;
31
import org.gvsig.tools.i18n.I18nManager;
32
import org.gvsig.tools.task.SimpleTaskStatus;
33
import org.slf4j.Logger;
34
import org.slf4j.LoggerFactory;
35
import org.xml.sax.Attributes;
36
import org.xml.sax.InputSource;
37
import org.xml.sax.Locator;
38
import org.xml.sax.SAXException;
39
import org.xml.sax.helpers.DefaultHandler;
40

    
41
/**
42
 *
43
 * @author jjdelcerro
44
 */
45
@SuppressWarnings("UseSpecificCatch")
46
public class CopyXML2dbImpl {
47

    
48
    private static final Logger LOGGER = LoggerFactory.getLogger(CopyXML2dbImpl.class);
49
    
50
    private static class TableInfo {
51
        private final Map<String,TableInfo> tables;
52
        private final JDBCStoreParameters openStoreParams;
53
        private final String tableName;
54
        private FeatureStore store;
55
        private EditableFeature current_row;
56
        private int pkcounter;
57
        private EditableFeature last_row;
58
        private FeatureType featureType;
59
        private DataTransaction transaction;
60
        
61
        
62
        private TableInfo(Map<String,TableInfo> tables, JDBCStoreParameters openStoreParams, DataTransaction transaction) {
63
            this.tables = tables;
64
            this.openStoreParams = openStoreParams;
65
            this.tableName = openStoreParams.getTable();
66
            this.pkcounter = -1;
67
            this.transaction = transaction;
68

    
69
            FeatureStore theStore = null;
70
            try {
71
                DataManager dataManager = DALLocator.getDataManager();
72
                theStore = (FeatureStore) dataManager.openStore(
73
                        this.openStoreParams.getProviderName(),
74
                        openStoreParams
75
                );
76
                this.featureType = theStore.getDefaultFeatureTypeQuietly();
77
            } catch (Throwable t) {
78
                throw new RuntimeException("Can't get path from store '" + this.getTableName() + "'.", t);
79
            } finally {
80
                DisposeUtils.disposeQuietly(theStore);
81
            }
82

    
83
        }
84
        
85
        private int getNextPkValue() {
86
            FeatureStore theStore = null;
87
            try {
88
                DataManager dataManager = DALLocator.getDataManager();
89
                theStore = (FeatureStore) dataManager.openStore(
90
                        this.openStoreParams.getProviderName(),
91
                        openStoreParams
92
                );
93
                FeatureQuery query = theStore.createFeatureQuery();
94
                String pkName = this.featureType.getPrimaryKey()[0].getName();
95
                query.addAggregate("MAX", pkName);
96
                Feature f = theStore.findFirst(query);
97
                if(f != null){
98
                    Object x = f.get(pkName);
99
                    if(x != null){
100
                        return ((Number)x).intValue()+1;
101
                    }
102
                }
103
                return 1;
104
            } catch (Throwable t) {
105
                throw new RuntimeException("Can't get path from store '" + this.getTableName() + "'.", t);
106
            } finally {
107
                DisposeUtils.disposeQuietly(theStore);
108
            }
109
            
110
            
111
        }
112
        
113
        public void close() {
114
            try {
115
                this.insert();
116
                if( this.store!=null ) {
117
//                    System.out.println("###: close("+this.tableName+")");
118
                    this.store.finishEditing();
119
                    DisposeUtils.dispose(this.store);
120
                }
121
            } catch(Throwable t) {
122
                throw new RuntimeException("Can't close table '"+this.getTableName()+"'.", t);
123
            }
124
        }
125
        
126
        public String getTableName() {
127
            return this.tableName;
128
        }
129

    
130
        public FeatureStore getStore() {
131
            if( this.store == null ) {
132
                try {
133
//                    System.out.println("###: create store("+this.tableName+")");
134
                    DataManager dataManager = DALLocator.getDataManager();                
135
                    this.store = (FeatureStore) dataManager.openStore(
136
                            this.transaction,
137
                            this.openStoreParams.getProviderName(), 
138
                            openStoreParams
139
                    );
140
                    this.store.edit(FeatureStore.MODE_APPEND);
141
                } catch(Throwable t) {
142
                    throw new RuntimeException("Can't open and start edit store '"+this.getTableName()+"'.", t);
143
                }
144
            }
145
            return this.store;
146
        }
147
        
148
        public Feature current_row() {
149
            return this.current_row;
150
        }
151

    
152
        private void createRow() {
153
            try {
154
                if(this.pkcounter < 0){
155
                    this.pkcounter = getNextPkValue();
156
                }
157
                FeatureStore theStore = this.getStore();
158
//                System.out.println("###: create row("+this.tableName+")");
159
                this.current_row = theStore.createNewFeature();
160
                this.last_row = this.current_row;
161
                FeatureType ft = this.current_row.getType();
162
                for (FeatureAttributeDescriptor attrdesc : ft) {
163
                    if( attrdesc.isPrimaryKey() ) {
164
                       this.set(attrdesc.getName(), this.pkcounter++);
165
                    } else if( attrdesc.isForeingKey() ) {
166
                        ForeingKey fk = attrdesc.getForeingKey();
167
                        TableInfo table = this.tables.get(fk.getTableName().toLowerCase());
168
                        if( table != null ) {
169
                            this.set(attrdesc.getName(), table.getPkValue());
170
                        }
171
                    }
172
                }
173
            } catch(Throwable t) {
174
                throw new RuntimeException("Can't create feature of store '"+this.getTableName()+"'.", t);
175
            }
176
        }
177

    
178
        private void set(String name, Object value) {
179
            if( this.current_row != null ) {
180
//                System.out.println("###: set("+this.tableName+", "+name+", "+Objects.toString(value)+")");
181
                try {
182
                    if( this.current_row.getType().get(name) == null ) {
183
                        LOGGER.info("Not exists attribute '"+name+"' in "+ this.getStore().getName());
184
                        throw new IllegalArgumentException("Not exists attribute '"+name+"' in "+ this.getStore().getName());
185
                    }
186
                    this.current_row.set(name, value);
187
                } catch(RuntimeException ex) {
188
                    LOGGER.info("Can't set attribute '"+name+"' in "+ this.getStore().getName()); //, ex);
189
                    throw ex;
190
                }
191
            }
192
        }
193

    
194
        private void insert() {
195
            if( this.store!=null && this.current_row!=null ) {
196
                try {
197
                    
198
                    FeatureType ft = this.current_row.getType();
199
                    for (FeatureAttributeDescriptor attrdesc : ft) {
200
                        if( attrdesc.isForeingKey() ) {
201
                            ForeingKey fk = attrdesc.getForeingKey();
202
                            TableInfo table = this.tables.get(fk.getTableName().toLowerCase());
203
                            if( table != null ) {
204
                                if( current_row.isNull(attrdesc.getName())){
205
                                    this.set(attrdesc.getName(), table.getPkValue());
206
                                }
207
                            }
208
                        }
209
                    }
210
                    
211
//                    System.out.println("###: insert("+this.tableName+")");
212
                    this.store.insert(current_row);
213
                } catch(Throwable t) {
214
                    throw new RuntimeException("Can't insert feature into store '"+this.getTableName()+"'.", t);
215
                }
216
            }
217
            this.current_row = null;
218
        }
219

    
220
        private Object getPkValue() {
221
            if( this.last_row==null ) {
222
                return null;
223
            }
224
            FeatureAttributeDescriptor[] attrdescs = this.last_row.getType().getPrimaryKey();
225
            return this.last_row.get(attrdescs[0].getName());
226
        }
227
        
228
        public String getPath() {
229
            return this.featureType.getTags().getString("xml2db.path", null);
230
        }
231

    
232
        public String getTablePrefix() {
233
            return this.featureType.getTags().getString("xml2db.tableprefix", null);
234
        }
235

    
236
        public boolean containsAttr(String attrname) {
237
            return this.featureType.get(attrname) != null;
238
        }
239
    }
240
    
241
    public void copyData(InputSource is, JDBCServerExplorerParameters dbparams, long countLines, String tablesPrefix, SimpleTaskStatus taskStatus) {
242
        if( is == null || is.getCharacterStream()==null ) {
243
            throw new IllegalArgumentException("reader is null");
244
        }
245
        DataManager dataManager = DALLocator.getDataManager();                        
246
        JDBCServerExplorer explorer = null;
247
        try {
248
            explorer = (JDBCServerExplorer) dataManager.openServerExplorer(dbparams.getProviderName(), dbparams);
249
        } catch (Exception ex) {
250
            throw new IllegalArgumentException("Can't open target database", ex);
251
        }
252
        I18nManager i18n = ToolsLocator.getI18nManager();
253
        MutableInt line = new MutableInt(0);
254
        MutableInt column = new MutableInt(0);
255
        DataTransaction trans = dataManager.createTransaction();
256
        try {
257
            trans.add(explorer);
258
            taskStatus.message(i18n.getTranslation("_Copying"));
259
            taskStatus.setRangeOfValues(0, countLines);
260
            
261
            SAXParserFactory spf = SAXParserFactory.newInstance();
262
            spf.setNamespaceAware(true);
263
            SAXParser saxParser = spf.newSAXParser();
264
            
265
            List<String> path = new ArrayList<>();
266
            Map<String,TableInfo> tables = new HashMap<>();
267
            for (DataStoreParameters openStoreParams0 : explorer.list()) {
268
                JDBCStoreParameters openStoreParams = (JDBCStoreParameters) openStoreParams0;
269
                TableInfo table = new TableInfo(tables, openStoreParams, trans);
270
                tables.put(table.getTableName().toLowerCase(), table);
271
            }
272
            
273
            saxParser.parse(is, new DefaultHandler() {
274
                private Locator locator;
275
                private StringBuilder valueBuilder;
276
                int refreshInterval = 1;
277
                
278
                @Override
279
                public void setDocumentLocator(Locator locator) {
280
                    this.locator = locator;
281
                }
282
                
283
                @Override
284
                public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
285
                    line.setValue(this.locator.getLineNumber());
286
                    column.setValue(this.locator.getColumnNumber()-2-localName.length());
287

    
288
                    if(line.intValue() % refreshInterval == 0) {
289
                        taskStatus.setCurValue(line.intValue());
290
                    }
291
                    
292
                    if(line.intValue() > 100000){
293
                        refreshInterval = 10000;
294
                    } else if(line.intValue() > 10000){
295
                        refreshInterval = 1000;
296
                    } else if(line.intValue() > 1000){
297
                        refreshInterval = 100;
298
                    } else if(line.intValue() > 100){
299
                        refreshInterval = 10;
300
                    }
301

    
302

    
303
                    try {
304
                        path.add(localName);
305
                        String path_s = StringUtils.join(path, "/");
306
                        TableInfo table1 = getTableByPath(tablesPrefix, tables, path_s);
307
                        if( table1 != null ) {
308
                            table1.createRow();
309
                            for (int i = 0; i < attributes.getLength(); i++) {
310
                                String name = attributes.getLocalName(i);
311
                                String value = attributes.getValue(i);
312
                                table1.set(name, value);
313
                            }
314
                        }
315
                    } catch(Exception ex) {
316
                        LOGGER.warn("Can't process startElement (line "+line+", column "+column+")",ex);
317
                    }
318
                    this.valueBuilder = null;
319
                }
320
                
321
                @Override
322
                public void endElement(String uri, String localName, String qName) throws SAXException {
323
                    line.setValue(this.locator.getLineNumber());
324
                    column.setValue(this.locator.getColumnNumber()-2-localName.length());
325

    
326
//                    taskStatus.setCurValue(line.intValue());
327
                    try {
328
                        String path_s = StringUtils.join(path, "/");
329
                        TableInfo table1 = getTableByPath(tablesPrefix, tables, path_s);
330
                        if(table1 != null) {
331
                            if (this.valueBuilder != null) {
332
                                String value = StringUtils.trimToNull(this.valueBuilder.toString());
333
                                if (value != null) {
334
                                    table1.set(localName + "$v", value);
335
                                }
336
                            }
337
                            
338
                            table1.insert();
339
                        } else if( path.size()>1 ) {
340
                            List<String> parentpath = path.subList(0, path.size()-1);
341
                            String parentpath_s = StringUtils.join(parentpath, "/");
342
                            String attrname = FilenameUtils.getBaseName(path_s);
343

    
344
                            TableInfo table2 = getTableByPath(tablesPrefix, tables, parentpath_s);
345
                            if( table2!=null ) {
346
                                if( this.valueBuilder!=null ) {
347
                                    String value = StringUtils.trimToNull(this.valueBuilder.toString());  
348
                                    if( value != null ) {
349
                                        table2.set(attrname,value);
350
                                    }
351
                                }
352
                            }
353
                        }
354
                    } catch(Exception ex) {
355
                        LOGGER.warn("Can't process endElement (line "+line+", column "+column+")",ex);
356
                    }
357
                    this.valueBuilder = null;
358
                    path.remove(path.size()-1);
359
                }
360
                
361
                @Override
362
                public void characters(char[] ch, int start, int length) throws SAXException {
363
                    line.setValue(this.locator.getLineNumber());
364
//                    taskStatus.setCurValue(line.intValue());
365

    
366
                    if( this.valueBuilder == null ) {
367
                        this.valueBuilder = new StringBuilder();
368
                    }
369
                    this.valueBuilder.append(ch, start, length);
370
                }
371
            });
372
            for (TableInfo table : tables.values() ) {
373
                table.close();
374
            }
375
            trans.commit();
376
        } catch (Exception ex) {
377
            DataTransaction.rollbackQuietly(trans);
378
            throw new RuntimeException("Can't copy data (line "+line+", column "+column+").", ex);
379
        } finally {
380
            DataTransaction.close(trans);
381
        }
382
        
383
    }
384

    
385
    private TableInfo getTableByPath(String tablesPrefix, Map<String,TableInfo> tables, String path) {
386
        for (TableInfo table : tables.values()) {
387
            if( StringUtils.equalsIgnoreCase(tablesPrefix, table.getTablePrefix()) &&
388
                StringUtils.equalsIgnoreCase(path, table.getPath())){
389
                return table;
390
            }
391
        }
392
        return null;
393
    }
394
    
395
    public void copyData(File xml, Charset charset, JDBCServerExplorerParameters dbparams, String tablesPrefix, SimpleTaskStatus taskStatus) {
396
        long count = Xml2dbCommons.countLines(xml, charset, taskStatus);
397
        
398
        InputSource is = Xml2dbCommons.openReader(xml, charset);
399
        copyData(is, dbparams, count, tablesPrefix, taskStatus);
400
    }
401
    
402
    public void copyData(InputStream xml, Charset charset, JDBCServerExplorerParameters dbparams, String tablesPrefix, SimpleTaskStatus taskStatus) {
403
        long count = -1; //Xml2dbCommons.countLines(xml, charset, taskStatus);
404
        InputSource is = Xml2dbCommons.openReader(xml, charset);
405
        copyData(is, dbparams, count, tablesPrefix, taskStatus);
406
    }
407
    
408
}