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 / StructureExtractorImpl.java @ 47606

History | View | Annotate | Download (23 KB)

1
/*
2
 * To change this license header, choose License Headers in Project Properties.
3
 * To change this template file, choose Tools | Templates
4
 * and open the template in the editor.
5
 */
6
package org.gvsig.xml2db.lib.impl;
7

    
8
import java.io.File;
9
import java.io.FileNotFoundException;
10
import java.io.IOException;
11
import java.io.InputStream;
12
import java.io.Reader;
13
import java.nio.charset.Charset;
14
import java.util.ArrayList;
15
import java.util.List;
16
import java.util.Locale;
17
import javax.xml.parsers.SAXParser;
18
import javax.xml.parsers.SAXParserFactory;
19
import org.apache.commons.lang3.ArrayUtils;
20
import org.apache.commons.lang3.StringUtils;
21
import org.apache.tika.utils.CharsetUtils;
22
import org.cresques.cts.IProjection;
23
import org.gvsig.fmap.crs.CRSFactory;
24
import org.gvsig.fmap.dal.DALLocator;
25
import org.gvsig.fmap.dal.DataManager;
26
import org.gvsig.fmap.dal.DataTypes;
27
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
28
import org.gvsig.fmap.dal.feature.EditableFeatureType;
29
import org.gvsig.fmap.dal.feature.EditableForeingKey;
30
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
31
import org.gvsig.tools.ToolsLocator;
32
import org.gvsig.tools.dynobject.DynField_v2;
33
import org.gvsig.tools.i18n.I18nManager;
34
import org.gvsig.tools.task.SimpleTaskStatus;
35
import org.gvsig.xml2db.lib.api.xmlinfo.XMLAttributeInfo;
36
import org.gvsig.xml2db.lib.api.xmlinfo.XMLInfo;
37
import org.gvsig.xml2db.lib.api.xmlinfo.XMLTableInfo;
38
import org.gvsig.xml2db.lib.impl.xmlinfo.XMLAttributeInfoImpl;
39
import org.gvsig.xml2db.lib.impl.xmlinfo.XMLInfoImpl;
40
import org.gvsig.xml2db.lib.impl.xmlinfo.XMLTableInfoImpl;
41
import org.slf4j.Logger;
42
import org.slf4j.LoggerFactory;
43
import org.xml.sax.Attributes;
44
import org.xml.sax.InputSource;
45
import org.xml.sax.Locator;
46
import org.xml.sax.SAXException;
47
import org.xml.sax.helpers.DefaultHandler;
48

    
49
/**
50
 *
51
 * @author jjdelcerro
52
 */
53
public class StructureExtractorImpl {
54

    
55
        private static final Logger LOGGER = LoggerFactory.getLogger(StructureExtractorImpl.class);
56
    private String tablePrefix;
57

    
58
    @SuppressWarnings("UseSpecificCatch")
59
    private void extractTags(XMLInfoImpl xmlinfo, Reader reader, SimpleTaskStatus status) {
60
        if( reader == null ) {
61
            throw new IllegalArgumentException("reader is null");
62
        }
63
        try {
64
            final DataManager dataManager = DALLocator.getDataManager();
65
            I18nManager i18n = ToolsLocator.getI18nManager();
66
            status.message(i18n.getTranslation("_Reading_xml")+" 1/5");
67
            status.setRangeOfValues(0, xmlinfo.getCountLines());
68
            
69
            SAXParserFactory spf = SAXParserFactory.newInstance();
70
            spf.setNamespaceAware(true);
71
            SAXParser saxParser = spf.newSAXParser();
72
            InputSource is = new InputSource(reader);
73
            
74
            List<String> path = new ArrayList<>();
75
            
76
            saxParser.parse(is, new DefaultHandler() {
77
                private Locator locator;
78
                int size;
79
                int refreshInterval = 1;
80
                StringBuilder chars = new StringBuilder();
81
                
82
                @Override
83
                public void setDocumentLocator(Locator locator) {
84
                    this.locator = locator;
85
                }
86
                
87
                @Override
88
                public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
89
                    int line = this.locator.getLineNumber();
90
                    int column = this.locator.getColumnNumber()-2-localName.length();
91

    
92
                    if(line % refreshInterval == 0) {
93
                        status.setCurValue(line);
94
                    }
95
                    
96
                    if(line > 100000){
97
                        refreshInterval = 10000;
98
                    } else if(line > 10000){
99
                        refreshInterval = 1000;
100
                    } else if(line > 1000){
101
                        refreshInterval = 100;
102
                    } else if(line > 100){
103
                        refreshInterval = 10;
104
                    }
105

    
106

    
107
                    String idvalue = dataManager.createUniqueID();
108
                    
109
                    path.add(localName);
110
                    String path_s = StringUtils.join(path, "/");
111
                    XMLAttributeInfoImpl info = xmlinfo.getTag(path_s);
112
                    if( info == null ) {
113
                        info = new XMLAttributeInfoImpl(xmlinfo.getLocale(), path_s);
114
                        xmlinfo.addTag(info);
115
                        
116
                    }
117
                    if( path.size()>1 ) {
118
                        List<String> parentpath = path.subList(0, path.size()-1);
119
                        String parentpath_s = StringUtils.join(parentpath, "/");
120
                        XMLAttributeInfoImpl parentinfo = xmlinfo.getTag(parentpath_s);
121
                        parentinfo.incrChildCount(localName);
122
                        parentinfo.setLastChildID(localName, idvalue);
123
                    }
124
                    
125
                    for (int i = 0; i < attributes.getLength(); i++) {
126
                        String name = attributes.getLocalName(i);                        
127
                        String value = attributes.getValue(i);
128
                        String idvalueChild = dataManager.createUniqueID();
129
                        XMLAttributeInfoImpl infoChild = xmlinfo.getTag(path_s+"/"+name);
130
                        if( infoChild == null ) {
131
                            infoChild = new XMLAttributeInfoImpl(xmlinfo.getLocale(), path_s+"/"+name);
132
                            xmlinfo.addTag(infoChild);
133
                        }
134
                        info.incrChildCount(infoChild.getName());
135
                        info.setLastChildID(infoChild.getName(), idvalueChild);
136
                        infoChild.addValue(value);
137
                        if( xmlinfo.getSrid() ==  null && StringUtils.containsIgnoreCase(infoChild.getName(), "srid") ) {
138
                            IProjection proj = getProjection(value);
139
                            if( proj!=null ) {
140
                                xmlinfo.setSrid(proj);
141
                            }
142
                        }
143
                    }
144
                    chars.setLength(0);
145
                }
146
                
147
                @Override
148
                public void endElement(String uri, String localName, String qName) throws SAXException {
149
                    int line = this.locator.getLineNumber();
150

    
151
//                    status.setCurValue(line);
152

    
153
                    String path_s = StringUtils.join(path, "/");
154
                    XMLAttributeInfoImpl info = xmlinfo.getTag(path_s);
155
                    if( info == null ) {
156
                        info = new XMLAttributeInfoImpl(xmlinfo.getLocale(), path_s);
157
                        xmlinfo.addTag(info);
158
                    }
159

    
160
                    XMLAttributeInfoImpl parentinfo = null;
161
                    if( path.size()>1 ) {
162
                        List<String> parentpath = path.subList(0, path.size()-1);
163
                        String parentpath_s = StringUtils.join(parentpath, "/");
164
                        parentinfo = xmlinfo.getTag(parentpath_s);
165
                    }
166
                    
167
                    if( info.hasChilds() || (parentinfo != null && (parentinfo.getChildsCount(localName)>1))) {
168
                        String value = this.chars.toString();
169
                        if( StringUtils.isNotBlank(value) ) {
170
                            String name = info.getName()+"$v";                        
171
                            String idvalueChild = dataManager.createUniqueID();
172
                            XMLAttributeInfoImpl infoChild = xmlinfo.getTag(path_s+"/"+name);
173
                            if( infoChild == null ) {
174
                                infoChild = new XMLAttributeInfoImpl(xmlinfo.getLocale(), path_s+"/"+name);
175
                                xmlinfo.addTag(infoChild);
176
                            }
177
                            info.incrChildCount(infoChild.getName());
178
                            info.setLastChildID(infoChild.getName(), idvalueChild);
179
                            infoChild.addValue(value);
180
                        }
181
                    } else {
182
                        String value = this.chars.toString();
183
                        info.addValue(value);
184
                        if( StringUtils.containsIgnoreCase(info.getName(), "srid") ) {
185
                            IProjection proj = getProjection(value);
186
                            if( proj!=null ) {
187
                                xmlinfo.setSrid(proj);
188
                            }
189
                        }
190
                    }
191
                    info.consolidateChildCounters();
192
//                    if( StringUtils.equalsIgnoreCase("LUGAR_CIRCULABA", info.getName()) ) {
193
//                        System.out.println("Oh!");
194
//                    }
195
                    
196
                    path.remove(path.size()-1);
197
                    chars.setLength(0);
198
                }
199
                
200
                @Override
201
                public void characters(char[] ch, int start, int length) throws SAXException {
202
                    int line = this.locator.getLineNumber();
203

    
204
//                    status.setCurValue(line);
205
                    this.chars.append(ch, start, length);
206
                }
207
                
208
                
209
            });
210
        } catch (Exception ex) {
211
            throw new RuntimeException("Can't extract tags.", ex);
212
        }
213
    }
214
    
215
    private IProjection getProjection(String value) {
216
        if( StringUtils.isBlank(value) ) {
217
            return null;
218
        }
219
        IProjection proj = null;
220
        try {
221
            proj = CRSFactory.getCRS(value);
222
        } catch(Throwable t) {
223
            
224
        }
225
        if( proj != null ) {
226
            return proj;
227
        }
228
        try {
229
            proj = CRSFactory.getCRS("EPSG:"+value);
230
        } catch(Throwable t) {
231
            
232
        }
233
        return proj;
234
    }
235
    
236
    public XMLInfo extractStructure(File xml, Charset charset, IProjection projection, Locale locale, SimpleTaskStatus status) throws FileNotFoundException, IOException {
237
        XMLInfoImpl xmlinfo = new XMLInfoImpl();
238
        xmlinfo.setTablePrefix(this.tablePrefix);
239
        xmlinfo.setLocale(locale);
240
        xmlinfo.setSrid(projection);
241
        xmlinfo.setTablePrefix(tablePrefix);
242
        long count = Xml2dbCommons.countLines(xml, charset, status);
243
        xmlinfo.setCountLines(count);
244
        InputSource is = Xml2dbCommons.openReader(xml,charset);
245
        return extractStructure(is, xmlinfo, status);
246
    }
247
    
248
    public XMLInfo extractStructure(InputStream xml, Charset charset, IProjection projection, Locale locale, SimpleTaskStatus status) throws IOException  {
249
        XMLInfoImpl xmlinfo = new XMLInfoImpl();
250
        xmlinfo.setLocale(locale);
251
        xmlinfo.setSrid(projection);
252
        xmlinfo.setTablePrefix(tablePrefix);
253
//        long count = Xml2dbCommons.countLines(xml, charset, status);
254
        xmlinfo.setCountLines(-1);
255
        InputSource is = Xml2dbCommons.openReader(xml, charset);
256
        return extractStructure(is, xmlinfo, status);
257
    }
258
    
259
    public XMLInfo extractStructure(Reader reader, IProjection projection, Locale locale, SimpleTaskStatus status) {
260
        XMLInfoImpl xmlinfo = new XMLInfoImpl();
261
        xmlinfo.setLocale(locale);
262
        xmlinfo.setSrid(projection);
263
        xmlinfo.setTablePrefix(tablePrefix);
264
        InputSource is = new InputSource(reader);
265
        return extractStructure(is, xmlinfo, status);
266
    }
267
    
268
    public XMLInfo extractStructure(InputSource is, XMLInfoImpl xmlinfo, SimpleTaskStatus status) {
269
        
270
        if( xmlinfo.getCharset()==null ) {
271
            xmlinfo.setCharset(CharsetUtils.forName(is.getEncoding()));
272
        }
273
        
274
        extractTags(xmlinfo, is.getCharacterStream(), status);
275
        
276
        buildTablesFromTags(xmlinfo, status);
277

    
278
        removeDuplicateTableNames(xmlinfo, status);
279
        
280
        createPrimaryKeyAndForeignKeys(xmlinfo, status);
281
        
282
        createFeatureTypes(xmlinfo, status);
283

    
284
        return xmlinfo;
285
    }
286
    
287
    private String plural(String s) {
288
        int l = s.length();
289
        char ch = s.substring(l-1,l).toLowerCase().charAt(0);
290
        if( ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u' ) {
291
            return s+"s";
292
        }
293
        return s+"es";
294
    }
295

    
296
    private void buildTablesFromTags(XMLInfoImpl xmlinfo, SimpleTaskStatus status) {
297
        I18nManager i18n = ToolsLocator.getI18nManager();
298
        status.message(i18n.getTranslation("_Identifying_tables")+" 2/5");
299
        status.setRangeOfValues(0, xmlinfo.getTagsPaths().size());
300
        
301
        for (String tagPath : xmlinfo.getTagsPaths()) {
302
            XMLAttributeInfoImpl tag1Info = xmlinfo.getTagInfo(tagPath);
303
//            System.out.println(tag1Info.getPath());
304
            XMLTableInfoImpl tableInfo = new XMLTableInfoImpl(tagPath, tag1Info);
305
            for (String tagPath2 : xmlinfo.getTagsPaths()) {
306
                if( tagPath.equals(tagPath2) ) {
307
                    continue;
308
                }
309
                if( tagPath2.startsWith(tagPath+"/") ) {
310
                    String fieldName = tagPath2.substring(tagPath.length()+1);
311
                    if( !fieldName.contains("/") ) {
312
                        XMLAttributeInfoImpl info = xmlinfo.getTag(tagPath2);
313
                        tableInfo.add(info);
314
                    }
315
                }
316
            }
317
            if( !tableInfo.isEmpty() ) {
318
                xmlinfo.addTable(tableInfo);
319
            }
320
            status.incrementCurrentValue();
321
        }
322
    }
323
    
324
    private void removeDuplicateTableNames(XMLInfoImpl xmlinfo, SimpleTaskStatus status) {
325
        I18nManager i18n = ToolsLocator.getI18nManager();
326
        status.message(i18n.getTranslation("_Fixing_table_names")+" 3/5");
327
        status.setRangeOfValues(0, xmlinfo.size());
328

    
329
        // Tratamos de corregir nombres duplicados en las tablas.
330
        for (XMLTableInfo tableInfo01 : xmlinfo) {
331
            XMLTableInfoImpl tableInfo1 = (XMLTableInfoImpl) tableInfo01;
332
            
333
            status.message(i18n.getTranslation("_Fixing_table_names")+" 3/5 ("+tableInfo1.getName()+")");
334

    
335
            boolean renombrar = false;
336
            for (XMLTableInfo tableInfo02 : xmlinfo) {
337
                XMLTableInfoImpl tableInfo2 = (XMLTableInfoImpl) tableInfo02;
338
                if( tableInfo1 == tableInfo2 ) {
339
                    continue;
340
                }
341
                if( StringUtils.equalsIgnoreCase(tableInfo1.getName(), tableInfo2.getName()) ) {
342
                    // FIXME: solo usa los dos ultimos nombres, podrian coincidir igualmente!!
343
                    String[] path_ss = tableInfo2.getPath().split("/");
344
                    int l = path_ss.length;
345
                    String name = path_ss[l-1]+"_"+path_ss[l-2];
346
                    tableInfo2.rename(name);
347
                    renombrar = true;
348
//                    System.out.println("###: Tablas con el mismo nombre, renombrado a "+name);
349
//                    System.out.println("###: "+tableInfo1.getPath());
350
//                    System.out.println("###: "+tableInfo2.getPath());
351
                }
352
            }
353
            if( renombrar ) {
354
                // FIXME: solo usa los dos ultimos nombres, podrian coincidir igualmente!!
355
                String[] path_ss = tableInfo1.getPath().split("/");
356
                int l = path_ss.length;
357
                String name = path_ss[l-1]+"_"+path_ss[l-2];
358
                tableInfo1.rename(name);
359
            }
360
            status.incrementCurrentValue();
361
        }
362
    }
363
    
364
    private void createPrimaryKeyAndForeignKeys(XMLInfoImpl xmlinfo, SimpleTaskStatus status) {
365
        I18nManager i18n = ToolsLocator.getI18nManager();
366
        status.message(i18n.getTranslation("_Identifying_foreign_keys")+" 4/5");
367
        status.setRangeOfValues(0, xmlinfo.size());
368

    
369
        for (XMLTableInfo tableInfo0 : xmlinfo) {
370
            XMLTableInfoImpl tableInfo = (XMLTableInfoImpl) tableInfo0;
371
            
372
            status.message(i18n.getTranslation("_Identifying_foreign_keys")+" 4/5 ("+tableInfo.getName()+")");
373

    
374
            String[] fieldkeys = tableInfo.getPath().split("/");
375
            for (int i = 0; i < fieldkeys.length; i++) {
376
                String fieldkey = fieldkeys[i];
377
                if( i==fieldkeys.length-1 ) {
378
                    tableInfo.add(new XMLAttributeInfoImpl(xmlinfo.getLocale(), "$ID_"+tableInfo.getName(), DataTypes.INT).setPk(true));
379
                } else { 
380
                    // TODO es una relacion 1:1
381
                    XMLTableInfo tableInfo2 = xmlinfo.getTableByPath(StringUtils.join(ArrayUtils.subarray(fieldkeys, 0, i+1),"/"));
382
                    tableInfo.add(new XMLAttributeInfoImpl(xmlinfo.getLocale(), "$ID_"+tableInfo2.getName(), DataTypes.INT)
383
                            .setFk(true)
384
                            .setFkCodeName("$ID_"+fieldkey)
385
                            .setFkTableName(fieldkey)
386
                    );
387
                }
388
            }
389

    
390
            for (XMLAttributeInfo field0 : tableInfo) {
391
                XMLAttributeInfoImpl field = (XMLAttributeInfoImpl) field0;
392
                if( xmlinfo.existsTableByPath(tableInfo.getPath()+"/"+field.getName()) ) {
393
                    XMLTableInfoImpl fktableInfo = xmlinfo.getTableByPath(tableInfo.getPath()+"/"+field.getName());
394
                    int count = tableInfo.getMaxCountChild(field.getName());
395
                    if( count<1 ) {
396
                        // Do nothing
397
                    } else if( count>1 ) {
398
                        // TODO es una relacion 1:n
399
                        field.setAggregate(true);
400
                        field.setFkCodeName("$ID_"+tableInfo.getName());
401
                        field.setFkTableName(fktableInfo.getName());
402
                        field.setSize(45);
403
                        field.setType(DataTypes.LIST);
404
                    } else {
405
                        // TODO es una relacion 1:1
406
                        field.setFk(true);
407
                        field.setFkCodeName("$ID_"+fktableInfo.getName());
408
                        field.setFkTableName(fktableInfo.getName());
409
                        field.setSize(0);
410
                        field.setType(DataTypes.INT);
411
                    }
412
                }
413
            }            
414
            tableInfo.sort();
415
//            System.out.println(tableInfo);
416
            status.incrementCurrentValue();
417
        }
418
    }
419
    
420
    private void createFeatureTypes(XMLInfoImpl xmlinfo, SimpleTaskStatus status) {
421
        I18nManager i18n = ToolsLocator.getI18nManager();
422
        status.message(i18n.getTranslation("_Creating_table_definitions")+" 5/5");
423
        status.setRangeOfValues(0, xmlinfo.size());
424

    
425
        DataManager dataManager = DALLocator.getDataManager();
426

    
427
        for (XMLTableInfo tableInfo0 : xmlinfo) {
428
            XMLTableInfoImpl tableInfo = (XMLTableInfoImpl) tableInfo0;
429

    
430
            status.message(i18n.getTranslation("_Creating_table_definitions")+" 5/5 ("+tableInfo.getName()+")");
431
            
432
            EditableFeatureType ft = dataManager.createFeatureType();
433
            ft.setLabel(tableInfo.getName());
434
            ft.getTags().set("xml2db.tablename", xmlinfo.getNameWithPrefix(tableInfo.getName()));
435
            ft.getTags().set("vcsgis.storename", xmlinfo.getNameWithPrefix(tableInfo.getName()));
436
            ft.getTags().set("xml2db.path", tableInfo.getPath());
437
            ft.getTags().set("xml2db.tableprefix", xmlinfo.getTablePrefix());
438
            for (XMLAttributeInfo attrinfo0 : tableInfo) {
439
                XMLAttributeInfoImpl attrinfo = (XMLAttributeInfoImpl) attrinfo0;
440
                if( ft.get(attrinfo.getName())!=null ) {
441
                    LOGGER.warn("Duplicated attribute '"+attrinfo.getName()+"' in '"+xmlinfo.getNameWithPrefix(tableInfo.getName())+"'.");
442
                }
443
                if(  attrinfo.isAggregate() ) {
444
                    continue;
445
                }
446
                EditableFeatureAttributeDescriptor attrdesc;
447
                if( attrinfo.getName().startsWith("$ID") ) {
448
                    attrdesc = ft.add(attrinfo.getName(), attrinfo.getType());
449
                    attrdesc.setLabel("Id. "+attrinfo.getName().substring(4));
450
                    attrdesc.setSize(attrinfo.getSize());
451
                } else if( attrinfo.getName().endsWith("$v") ) {
452
                    attrdesc = ft.add(attrinfo.getName(), attrinfo.getType());
453
                    attrdesc.setLabel(StringUtils.left(attrinfo.getName(),attrinfo.getName().length()-2));
454
                    attrdesc.setSize(attrinfo.getSize());
455
                } else {
456
                    attrdesc = ft.add(attrinfo.getName(), attrinfo.getType());
457
                    attrdesc.setSize(attrinfo.getSize());
458
                    attrdesc.setPrecision(attrinfo.getPrecision());
459
                    attrdesc.setScale(attrinfo.getScale());
460
                    if( attrdesc.getType()==DataTypes.GEOMETRY ) {
461
                        attrdesc.setGeometryType(attrinfo.getGeometryType());
462
                        attrdesc.setSRS(xmlinfo.getSrid());
463
                        attrdesc.setIsIndexed(true);
464
                    }
465
                }
466
                attrdesc.setLocale(xmlinfo.getLocale());
467
                attrdesc.setIsPrimaryKey(attrinfo.isPk());
468
                if( attrinfo.isFk() ) {
469
                    EditableForeingKey fk = attrdesc.getForeingKey();
470
                    fk.setForeingKey(true);
471
                    fk.setTableName(xmlinfo.getNameWithPrefix(attrinfo.getFkTableName()));
472
                    fk.setCodeName(attrinfo.getFkCodeName());
473
                    fk.setClosedList(false);
474
                    fk.setLabelFormula("\""+attrinfo.getFkCodeName()+"\"");
475
                    attrdesc.setRelationType(DynField_v2.RELATION_TYPE_COLLABORATION);
476
                    attrdesc.setIsIndexed(true);
477
                }
478
            }
479
            FeatureAttributeDescriptor pk = ft.getPrimaryKey()[0];
480
            for (XMLAttributeInfo attrinfo0 : tableInfo) {
481
                XMLAttributeInfoImpl attrinfo = (XMLAttributeInfoImpl) attrinfo0;
482
                if(  attrinfo.isAggregate() ) {
483
                    EditableFeatureAttributeDescriptor attrdesc = ft.add("$List_"+attrinfo.getName(), attrinfo.getType());
484
                    attrdesc.setLabel(plural(attrinfo.getName()));
485
                    attrdesc.getTags().set("dal.relatedfeatures.table", xmlinfo.getNameWithPrefix(attrinfo.getFkTableName()));
486
                    attrdesc.getTags().set("dal.relatedfeatures.unique.field.name", attrinfo.getFkCodeName());
487
                    attrdesc.getTags().set("dynform.label.empty", true);
488
                    attrdesc.getTags().set("dynform.resizeWeight", 100);
489
                    attrdesc.setFeatureAttributeEmulator(
490
                        "SELECT * FROM \""+xmlinfo.getNameWithPrefix(attrinfo.getFkTableName()) + "\" WHERE ( (\""+pk.getName()+"\") = (\""+xmlinfo.getNameWithPrefix(attrinfo.getFkTableName()) + "\".\""+pk.getName()+"\") )"                    
491
                    );
492
                    attrdesc.setRelationType(DynField_v2.RELATION_TYPE_AGGREGATE);
493
                }
494
            }
495
            tableInfo.setFeatureType(ft);
496
            status.incrementCurrentValue();
497
        }
498
    }
499
    
500
    public void setTablePrefix(String tablePrefix) {
501
        this.tablePrefix = tablePrefix;
502
    }
503
}