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 @ 47360

History | View | Annotate | Download (16.7 KB)

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

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

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

    
50
    private static final Logger LOGGER = LoggerFactory.getLogger(CopyXML2dbImpl.class);
51
    
52
    private static class TableInfo {
53
        private final Map<String,TableInfo> tables;
54
        private final JDBCStoreParameters openStoreParams;
55
        private final String tableName;
56
        private FeatureStore store;
57
        private EditableFeature current_row;
58
        private int pkcounter;
59
        private EditableFeature last_row;
60
        private FeatureType featureType;
61
        
62
        
63
        private TableInfo(Map<String,TableInfo> tables, JDBCStoreParameters openStoreParams) {
64
            this.tables = tables;
65
            this.openStoreParams = openStoreParams;
66
            this.tableName = openStoreParams.getTable();
67
            this.pkcounter = -1;
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.openStoreParams.getProviderName(), 
137
                            openStoreParams
138
                    );
139
                    this.store.edit(FeatureStore.MODE_APPEND);
140
                } catch(Throwable t) {
141
                    throw new RuntimeException("Can't open and start edit store '"+this.getTableName()+"'.", t);
142
                }
143
            }
144
            return this.store;
145
        }
146
        
147
        public Feature current_row() {
148
            return this.current_row;
149
        }
150

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

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

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

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

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

    
281
                    if(line.intValue() % refreshInterval == 0) {
282
                        taskStatus.setCurValue(line.intValue());
283
                    }
284
                    
285
                    if(line.intValue() > 100000){
286
                        refreshInterval = 10000;
287
                    } else if(line.intValue() > 10000){
288
                        refreshInterval = 1000;
289
                    } else if(line.intValue() > 1000){
290
                        refreshInterval = 100;
291
                    } else if(line.intValue() > 100){
292
                        refreshInterval = 10;
293
                    }
294

    
295

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

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

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

    
359
                    if( this.valueBuilder == null ) {
360
                        this.valueBuilder = new StringBuilder();
361
                    }
362
                    this.valueBuilder.append(ch, start, length);
363
                }
364
            });
365
            for (TableInfo table : tables.values() ) {
366
                table.close();
367
            }
368
        } catch (Exception ex) {
369
            throw new RuntimeException("Can't copy data (line "+line+", column "+column+").", ex);
370
        }
371
    }
372

    
373
    private TableInfo getTableByPath(Map<String,TableInfo> tables, String path) {
374
        for (TableInfo table : tables.values()) {
375
            if(StringUtils.equalsIgnoreCase(path, table.getPath())){
376
                return table;
377
            }
378
        }
379
        return null;
380
    }
381
    
382
    public void copyData(File xml, Charset charset, JDBCServerExplorerParameters dbparams, SimpleTaskStatus taskStatus) {
383
        long count = Xml2dbCommons.countLines(xml, charset, taskStatus);
384
        
385
        InputSource is = Xml2dbCommons.openReader(xml, charset);
386
        copyData(is, dbparams, count, taskStatus);
387
    }
388
    
389
    public void copyData(InputStream xml, Charset charset, JDBCServerExplorerParameters dbparams, SimpleTaskStatus taskStatus) {
390
        long count = -1; //Xml2dbCommons.countLines(xml, charset, taskStatus);
391
        InputSource is = Xml2dbCommons.openReader(xml, charset);
392
        copyData(is, dbparams, count, taskStatus);
393
    }
394
    
395
}