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

History | View | Annotate | Download (16.1 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
                
270
                @Override
271
                public void setDocumentLocator(Locator locator) {
272
                    this.locator = locator;
273
                }
274
                
275
                @Override
276
                public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
277
                    line.setValue(this.locator.getLineNumber());
278
                    column.setValue(this.locator.getColumnNumber()-2-localName.length());
279

    
280
                    taskStatus.setCurValue(line.intValue());
281
                    try {
282
                        path.add(localName);
283
                        String path_s = StringUtils.join(path, "/");
284
                        TableInfo table1 = getTableByPath(tables, path_s);
285
                        if( table1 != null ) {
286
                            table1.createRow();
287
                            for (int i = 0; i < attributes.getLength(); i++) {
288
                                String name = attributes.getLocalName(i);
289
                                String value = attributes.getValue(i);
290
                                table1.set(name, value);
291
                            }
292
                        }
293
                    } catch(Exception ex) {
294
                        LOGGER.warn("Can't process startElement (line "+line+", column "+column+")",ex);
295
                    }
296
                    this.valueBuilder = null;
297
                }
298
                
299
                @Override
300
                public void endElement(String uri, String localName, String qName) throws SAXException {
301
                    line.setValue(this.locator.getLineNumber());
302
                    column.setValue(this.locator.getColumnNumber()-2-localName.length());
303

    
304
                    taskStatus.setCurValue(line.intValue());
305
                    try {
306
                        String path_s = StringUtils.join(path, "/");
307
                        TableInfo table1 = getTableByPath(tables, path_s);
308
                        if(table1 != null) {
309
                            if (this.valueBuilder != null) {
310
                                String value = StringUtils.trimToNull(this.valueBuilder.toString());
311
                                if (value != null) {
312
                                    table1.set(localName + "$v", value);
313
                                }
314
                            }
315
                            
316
                            table1.insert();
317
                        } else if( path.size()>1 ) {
318
                            List<String> parentpath = path.subList(0, path.size()-1);
319
                            String parentpath_s = StringUtils.join(parentpath, "/");
320
                            String attrname = FilenameUtils.getBaseName(path_s);
321

    
322
                            TableInfo table2 = getTableByPath(tables, parentpath_s);
323
                            if( table2!=null ) {
324
                                if( this.valueBuilder!=null ) {
325
                                    String value = StringUtils.trimToNull(this.valueBuilder.toString());  
326
                                    if( value != null ) {
327
                                        table2.set(attrname,value);
328
                                    }
329
                                }
330
                            }
331
                        }
332
                    } catch(Exception ex) {
333
                        LOGGER.warn("Can't process endElement (line "+line+", column "+column+")",ex);
334
                    }
335
                    this.valueBuilder = null;
336
                    path.remove(path.size()-1);
337
                }
338
                
339
                @Override
340
                public void characters(char[] ch, int start, int length) throws SAXException {
341
                    line.setValue(this.locator.getLineNumber());
342
                    taskStatus.setCurValue(line.intValue());
343

    
344
                    if( this.valueBuilder == null ) {
345
                        this.valueBuilder = new StringBuilder();
346
                    }
347
                    this.valueBuilder.append(ch, start, length);
348
                }
349
            });
350
            for (TableInfo table : tables.values() ) {
351
                table.close();
352
            }
353
        } catch (Exception ex) {
354
            throw new RuntimeException("Can't copy data (line "+line+", column "+column+").", ex);
355
        }
356
    }
357

    
358
    private TableInfo getTableByPath(Map<String,TableInfo> tables, String path) {
359
        for (TableInfo table : tables.values()) {
360
            if(StringUtils.equalsIgnoreCase(path, table.getPath())){
361
                return table;
362
            }
363
        }
364
        return null;
365
    }
366
    
367
    public void copyData(File xml, Charset charset, JDBCServerExplorerParameters dbparams, SimpleTaskStatus taskStatus) {
368
        long count = Xml2dbCommons.countLines(xml, charset, taskStatus);
369
        
370
        InputSource is = Xml2dbCommons.openReader(xml, charset);
371
        copyData(is, dbparams, count, taskStatus);
372
    }
373
    
374
    public void copyData(InputStream xml, Charset charset, JDBCServerExplorerParameters dbparams, SimpleTaskStatus taskStatus) {
375
        long count = Xml2dbCommons.countLines(xml, charset, taskStatus);
376
        InputSource is = Xml2dbCommons.openReader(xml, charset);
377
        copyData(is, dbparams, count, taskStatus);
378
    }
379
    
380
}