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

History | View | Annotate | Download (14.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.DataStoreParameters;
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.FeatureStore;
23
import org.gvsig.fmap.dal.feature.FeatureType;
24
import org.gvsig.fmap.dal.feature.ForeingKey;
25
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
26
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
27
import org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorer;
28
import org.gvsig.tools.dispose.DisposeUtils;
29
import org.gvsig.tools.task.SimpleTaskStatus;
30
import org.gvsig.xml2db.lib.impl.xmlinfo.XMLTableInfoImpl;
31
import org.slf4j.Logger;
32
import org.slf4j.LoggerFactory;
33
import org.xml.sax.Attributes;
34
import org.xml.sax.InputSource;
35
import org.xml.sax.Locator;
36
import org.xml.sax.SAXException;
37
import org.xml.sax.helpers.DefaultHandler;
38

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

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

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

    
79
        }
80
        
81
        public void close() {
82
            try {
83
                this.insert();
84
                if( this.store!=null ) {
85
//                    System.out.println("###: close("+this.tableName+")");
86
                    this.store.finishEditing();
87
                    DisposeUtils.dispose(this.store);
88
                }
89
            } catch(Throwable t) {
90
                throw new RuntimeException("Can't close table '"+this.getTableName()+"'.", t);
91
            }
92
        }
93
        
94
        public String getTableName() {
95
            return this.tableName;
96
        }
97

    
98
        public FeatureStore getStore() {
99
            if( this.store == null ) {
100
                try {
101
//                    System.out.println("###: create store("+this.tableName+")");
102
                    DataManager dataManager = DALLocator.getDataManager();                
103
                    this.store = (FeatureStore) dataManager.openStore(
104
                            this.openStoreParams.getProviderName(), 
105
                            openStoreParams
106
                    );
107
                    this.store.edit(FeatureStore.MODE_APPEND);
108
                } catch(Throwable t) {
109
                    throw new RuntimeException("Can't open and start edit store '"+this.getTableName()+"'.", t);
110
                }
111
            }
112
            return this.store;
113
        }
114
        
115
        public Feature current_row() {
116
            return this.current_row;
117
        }
118

    
119
        private void createRow() {
120
            try {
121
                FeatureStore theStore = this.getStore();
122
//                System.out.println("###: create row("+this.tableName+")");
123
                this.current_row = theStore.createNewFeature();
124
                this.last_row = this.current_row;
125
                FeatureType ft = this.current_row.getType();
126
                for (FeatureAttributeDescriptor attrdesc : ft) {
127
                    if( attrdesc.isPrimaryKey() ) {
128
                       this.set(attrdesc.getName(), this.pkcounter++);
129
                    } else if( attrdesc.isForeingKey() ) {
130
                        ForeingKey fk = attrdesc.getForeingKey();
131
                        TableInfo table = this.tables.get(fk.getTableName().toLowerCase());
132
                        if( table != null ) {
133
                            this.set(attrdesc.getName(), table.getPkValue());
134
                        }
135
                    }
136
                }
137
            } catch(Throwable t) {
138
                throw new RuntimeException("Can't create feature of store '"+this.getTableName()+"'.", t);
139
            }
140
        }
141

    
142
        private void set(String name, Object value) {
143
            if( this.current_row != null ) {
144
//                System.out.println("###: set("+this.tableName+", "+name+", "+Objects.toString(value)+")");
145
                try {
146
                    if( this.current_row.getType().get(name) == null ) {
147
                        LOGGER.info("Not exists attribute '"+name+"' in "+ this.getStore().getName());
148
                        throw new IllegalArgumentException("Not exists attribute '"+name+"' in "+ this.getStore().getName());
149
                    }
150
                    this.current_row.set(name, value);
151
                } catch(RuntimeException ex) {
152
                    LOGGER.info("Can't set attribute '"+name+"' in "+ this.getStore().getName()); //, ex);
153
                    throw ex;
154
                }
155
            }
156
        }
157

    
158
        private void insert() {
159
            if( this.store!=null && this.current_row!=null ) {
160
                try {
161
                    
162
                    FeatureType ft = this.current_row.getType();
163
                    for (FeatureAttributeDescriptor attrdesc : ft) {
164
                        if( attrdesc.isForeingKey() ) {
165
                            ForeingKey fk = attrdesc.getForeingKey();
166
                            TableInfo table = this.tables.get(fk.getTableName().toLowerCase());
167
                            if( table != null ) {
168
                                if( current_row.isNull(attrdesc.getName())){
169
                                    this.set(attrdesc.getName(), table.getPkValue());
170
                                }
171
                            }
172
                        }
173
                    }
174
                    
175
//                    System.out.println("###: insert("+this.tableName+")");
176
                    this.store.insert(current_row);
177
                } catch(Throwable t) {
178
                    throw new RuntimeException("Can't insert feature into store '"+this.getTableName()+"'.", t);
179
                }
180
            }
181
            this.current_row = null;
182
        }
183

    
184
        private Object getPkValue() {
185
            if( this.last_row==null ) {
186
                return null;
187
            }
188
            FeatureAttributeDescriptor[] attrdescs = this.last_row.getType().getPrimaryKey();
189
            return this.last_row.get(attrdescs[0].getName());
190
        }
191
        
192
        public String getPath() {
193
            return this.featureType.getTags().getString("xml2db.path", null);
194
        }
195

    
196
        public boolean containsAttr(String attrname) {
197
            return this.featureType.get(attrname) != null;
198
        }
199
    }
200
    
201
    public void copyData(InputSource is, JDBCServerExplorerParameters dbparams, long countLines, SimpleTaskStatus taskStatus) {
202
        if( is == null || is.getCharacterStream()==null ) {
203
            throw new IllegalArgumentException("reader is null");
204
        }
205
        DataManager dataManager = DALLocator.getDataManager();                        
206
        JDBCServerExplorer explorer = null;
207
        try {
208
            explorer = (JDBCServerExplorer) dataManager.openServerExplorer(dbparams.getProviderName(), dbparams);
209
        } catch (Exception ex) {
210
            throw new IllegalArgumentException("Can't open target database", ex);
211
        }
212
        MutableInt line = new MutableInt(0);
213
        MutableInt column = new MutableInt(0);
214
        try {
215
            taskStatus.message("Copying...");
216
            taskStatus.setRangeOfValues(0, countLines);
217
            
218
            SAXParserFactory spf = SAXParserFactory.newInstance();
219
            spf.setNamespaceAware(true);
220
            SAXParser saxParser = spf.newSAXParser();
221
            
222
            List<String> path = new ArrayList<>();
223
            Map<String,TableInfo> tables = new HashMap<>();
224
            for (DataStoreParameters openStoreParams0 : explorer.list()) {
225
                JDBCStoreParameters openStoreParams = (JDBCStoreParameters) openStoreParams0;
226
                TableInfo table = new TableInfo(tables, openStoreParams);
227
                tables.put(table.getTableName().toLowerCase(), table);
228
            }
229
            
230
            saxParser.parse(is, new DefaultHandler() {
231
                private Locator locator;
232
                private StringBuilder valueBuilder;
233
                
234
                @Override
235
                public void setDocumentLocator(Locator locator) {
236
                    this.locator = locator;
237
                }
238
                
239
                @Override
240
                public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
241
                    line.setValue(this.locator.getLineNumber());
242
                    column.setValue(this.locator.getColumnNumber()-2-localName.length());
243

    
244
                    taskStatus.setCurValue(line.intValue());
245
                    try {
246
                        path.add(localName);
247
                        String path_s = StringUtils.join(path, "/");
248
                        TableInfo table1 = getTableByPath(tables, path_s);
249
                        if( table1 != null ) {
250
                            table1.createRow();
251
                            for (int i = 0; i < attributes.getLength(); i++) {
252
                                String name = attributes.getLocalName(i);
253
                                String value = attributes.getValue(i);
254
                                table1.set(name, value);
255
                            }
256
                        }
257
                    } catch(Exception ex) {
258
                        LOGGER.warn("Can't process startElement (line "+line+", column "+column+")",ex);
259
                    }
260
                    this.valueBuilder = null;
261
                }
262
                
263
                @Override
264
                public void endElement(String uri, String localName, String qName) throws SAXException {
265
                    line.setValue(this.locator.getLineNumber());
266
                    column.setValue(this.locator.getColumnNumber()-2-localName.length());
267

    
268
                    taskStatus.setCurValue(line.intValue());
269
                    try {
270
                        String path_s = StringUtils.join(path, "/");
271
                        TableInfo table1 = getTableByPath(tables, path_s);
272
                        if(table1 != null) {
273
                            if (this.valueBuilder != null) {
274
                                String value = StringUtils.trimToNull(this.valueBuilder.toString());
275
                                if (value != null) {
276
                                    table1.set(localName + "$v", value);
277
                                }
278
                            }
279
                            
280
                            table1.insert();
281
                        } else if( path.size()>1 ) {
282
                            List<String> parentpath = path.subList(0, path.size()-1);
283
                            String parentpath_s = StringUtils.join(parentpath, "/");
284
                            String attrname = FilenameUtils.getBaseName(path_s);
285

    
286
                            TableInfo table2 = getTableByPath(tables, parentpath_s);
287
                            if( table2!=null ) {
288
                                if( this.valueBuilder!=null ) {
289
                                    String value = StringUtils.trimToNull(this.valueBuilder.toString());  
290
                                    if( value != null ) {
291
                                        table2.set(attrname,value);
292
                                    }
293
                                }
294
                            }
295
                        }
296
                    } catch(Exception ex) {
297
                        LOGGER.warn("Can't process endElement (line "+line+", column "+column+")",ex);
298
                    }
299
                    this.valueBuilder = null;
300
                    path.remove(path.size()-1);
301
                }
302
                
303
                @Override
304
                public void characters(char[] ch, int start, int length) throws SAXException {
305
                    line.setValue(this.locator.getLineNumber());
306
                    taskStatus.setCurValue(line.intValue());
307

    
308
                    if( this.valueBuilder == null ) {
309
                        this.valueBuilder = new StringBuilder();
310
                    }
311
                    this.valueBuilder.append(ch, start, length);
312
                }
313
            });
314
            for (TableInfo table : tables.values() ) {
315
                table.close();
316
            }
317
        } catch (Exception ex) {
318
            throw new RuntimeException("Can't copy data (line "+line+", column "+column+").", ex);
319
        }
320
    }
321

    
322
    private TableInfo getTableByPath(Map<String,TableInfo> tables, String path) {
323
        for (TableInfo table : tables.values()) {
324
            if(StringUtils.equalsIgnoreCase(path, table.getPath())){
325
                return table;
326
            }
327
        }
328
        return null;
329
    }
330
    
331
    public void copyData(File xml, Charset charset, JDBCServerExplorerParameters dbparams, SimpleTaskStatus taskStatus) {
332
        long count = Xml2dbCommons.countLines(xml, charset, taskStatus);
333
        
334
        InputSource is = Xml2dbCommons.openReader(xml, charset);
335
        copyData(is, dbparams, count, taskStatus);
336
    }
337
    
338
    public void copyData(InputStream xml, Charset charset, JDBCServerExplorerParameters dbparams, SimpleTaskStatus taskStatus) {
339
        long count = Xml2dbCommons.countLines(xml, charset, taskStatus);
340
        InputSource is = Xml2dbCommons.openReader(xml, charset);
341
        copyData(is, dbparams, count, taskStatus);
342
    }
343
    
344
}