svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.file / org.gvsig.fmap.dal.file.dbf / src / main / java / org / gvsig / fmap / dal / store / dbf / DBFStoreProvider.java @ 46897
History | View | Annotate | Download (28 KB)
1 | 40559 | jjdelcerro | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | *
|
||
4 | * Copyright (C) 2007-2013 gvSIG Association.
|
||
5 | *
|
||
6 | 41483 | jjdelcerro | * This program is free software; you can redistribute it and/or modify it under
|
7 | * the terms of the GNU General Public License as published by the Free Software
|
||
8 | * Foundation; either version 3 of the License, or (at your option) any later
|
||
9 | * version.
|
||
10 | 40559 | jjdelcerro | *
|
11 | 41483 | jjdelcerro | * This program is distributed in the hope that it will be useful, but WITHOUT
|
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||
13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||
14 | * details.
|
||
15 | 40559 | jjdelcerro | *
|
16 | 41483 | jjdelcerro | * You should have received a copy of the GNU General Public License along with
|
17 | * this program; if not, write to the Free Software Foundation, Inc., 51
|
||
18 | * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
19 | 40559 | jjdelcerro | *
|
20 | 41483 | jjdelcerro | * For any additional information, do not hesitate to contact us at info AT
|
21 | * gvsig.com, or visit our website www.gvsig.com.
|
||
22 | 40559 | jjdelcerro | */
|
23 | 40435 | jjdelcerro | package org.gvsig.fmap.dal.store.dbf; |
24 | |||
25 | import java.io.File; |
||
26 | import java.io.IOException; |
||
27 | 44669 | jjdelcerro | import java.math.BigDecimal; |
28 | 40435 | jjdelcerro | import java.nio.charset.Charset; |
29 | import java.util.ArrayList; |
||
30 | import java.util.Iterator; |
||
31 | import java.util.List; |
||
32 | 45387 | omartinez | import java.util.logging.Level; |
33 | 40435 | jjdelcerro | |
34 | import org.apache.commons.io.FileUtils; |
||
35 | 45387 | omartinez | import org.apache.commons.lang3.StringUtils; |
36 | 42814 | fdiaz | |
37 | 40435 | jjdelcerro | import org.gvsig.fmap.dal.DALLocator; |
38 | import org.gvsig.fmap.dal.DataManager; |
||
39 | import org.gvsig.fmap.dal.DataServerExplorer; |
||
40 | 44669 | jjdelcerro | import org.gvsig.fmap.dal.DataStore; |
41 | 40435 | jjdelcerro | import org.gvsig.fmap.dal.DataStoreNotification; |
42 | import org.gvsig.fmap.dal.DataTypes; |
||
43 | import org.gvsig.fmap.dal.FileHelper; |
||
44 | import org.gvsig.fmap.dal.exception.CloseException; |
||
45 | import org.gvsig.fmap.dal.exception.DataException; |
||
46 | import org.gvsig.fmap.dal.exception.FileNotFoundException; |
||
47 | import org.gvsig.fmap.dal.exception.InitializeException; |
||
48 | import org.gvsig.fmap.dal.exception.OpenException; |
||
49 | import org.gvsig.fmap.dal.exception.ReadException; |
||
50 | import org.gvsig.fmap.dal.exception.UnsupportedVersionException; |
||
51 | import org.gvsig.fmap.dal.exception.ValidateDataParametersException; |
||
52 | import org.gvsig.fmap.dal.feature.EditableFeatureType; |
||
53 | import org.gvsig.fmap.dal.feature.Feature; |
||
54 | import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
||
55 | import org.gvsig.fmap.dal.feature.FeatureQuery; |
||
56 | import org.gvsig.fmap.dal.feature.FeatureSet; |
||
57 | import org.gvsig.fmap.dal.feature.FeatureStore; |
||
58 | import org.gvsig.fmap.dal.feature.FeatureType; |
||
59 | 44871 | jjdelcerro | import org.gvsig.fmap.dal.feature.FeatureType.FeatureTypeChanged; |
60 | 40597 | jldominguez | import org.gvsig.fmap.dal.feature.exception.AttributeNameException; |
61 | import org.gvsig.fmap.dal.feature.exception.AttributeNameTooLongException; |
||
62 | 40435 | jjdelcerro | import org.gvsig.fmap.dal.feature.exception.PerformEditingException; |
63 | import org.gvsig.fmap.dal.feature.spi.AbstractFeatureStoreProvider; |
||
64 | import org.gvsig.fmap.dal.feature.spi.FeatureProvider; |
||
65 | import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices; |
||
66 | import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider; |
||
67 | 45387 | omartinez | import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices; |
68 | 40435 | jjdelcerro | import org.gvsig.fmap.dal.resource.ResourceAction; |
69 | import org.gvsig.fmap.dal.resource.exception.ResourceException; |
||
70 | import org.gvsig.fmap.dal.resource.exception.ResourceExecuteException; |
||
71 | import org.gvsig.fmap.dal.resource.exception.ResourceNotifyChangesException; |
||
72 | import org.gvsig.fmap.dal.resource.exception.ResourceNotifyCloseException; |
||
73 | import org.gvsig.fmap.dal.resource.exception.ResourceNotifyOpenException; |
||
74 | import org.gvsig.fmap.dal.resource.file.FileResource; |
||
75 | import org.gvsig.fmap.dal.resource.spi.ResourceConsumer; |
||
76 | import org.gvsig.fmap.dal.resource.spi.ResourceProvider; |
||
77 | import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorer; |
||
78 | import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorerParameters; |
||
79 | import org.gvsig.fmap.dal.spi.DataStoreProviderServices; |
||
80 | import org.gvsig.fmap.dal.store.dbf.utils.DbaseFile; |
||
81 | 44669 | jjdelcerro | import org.gvsig.fmap.dal.store.dbf.utils.FieldFormatter; |
82 | 40435 | jjdelcerro | import org.gvsig.metadata.MetadataLocator; |
83 | import org.gvsig.metadata.MetadataManager; |
||
84 | import org.gvsig.metadata.exceptions.MetadataException; |
||
85 | 44472 | jjdelcerro | import org.gvsig.tools.dataTypes.CoercionException; |
86 | 40435 | jjdelcerro | import org.gvsig.tools.dispose.DisposableIterator; |
87 | import org.gvsig.tools.dynobject.DynObject; |
||
88 | import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException; |
||
89 | import org.gvsig.tools.exception.BaseException; |
||
90 | 44669 | jjdelcerro | import org.gvsig.tools.logger.FilteredLogger; |
91 | 42814 | fdiaz | |
92 | 42517 | dmartinezizquierdo | import org.slf4j.Logger; |
93 | import org.slf4j.LoggerFactory; |
||
94 | 40435 | jjdelcerro | |
95 | public class DBFStoreProvider extends AbstractFeatureStoreProvider implements |
||
96 | 41483 | jjdelcerro | ResourceConsumer { |
97 | 40435 | jjdelcerro | |
98 | private static final Logger LOG = LoggerFactory.getLogger(DBFStoreProvider.class); |
||
99 | |||
100 | 41746 | jjdelcerro | public static final int MAX_FIELD_NAME_LENGTH = DbaseFile.MAX_FIELD_NAME_LENGTH; |
101 | 40435 | jjdelcerro | |
102 | 44669 | jjdelcerro | public static final String NAME = DataStore.DBASE_PROVIDER_NAME; |
103 | public static final String DESCRIPTION = "DBF file"; |
||
104 | 40435 | jjdelcerro | |
105 | 41483 | jjdelcerro | public static final String METADATA_DEFINITION_NAME = NAME; |
106 | private static final String METADATA_ENCODING = "Encoding"; |
||
107 | private static final String METADATA_CODEPAGE = "CodePage"; |
||
108 | 40435 | jjdelcerro | |
109 | 41483 | jjdelcerro | private DbaseFile dbfFile = null; |
110 | private ResourceProvider dbfResource;
|
||
111 | private long counterNewsOIDs = -1; |
||
112 | private DBFFeatureWriter writer;
|
||
113 | 40435 | jjdelcerro | |
114 | 42517 | dmartinezizquierdo | private boolean loTengoEnUso; |
115 | |||
116 | 42814 | fdiaz | private boolean allowDuplicatedFieldNames; |
117 | 44669 | jjdelcerro | private FilteredLogger logger;
|
118 | 45387 | omartinez | |
119 | 46897 | fdiaz | protected EditableFeatureType featureType;
|
120 | 42814 | fdiaz | |
121 | 45387 | omartinez | |
122 | 41483 | jjdelcerro | protected static void registerMetadataDefinition() throws MetadataException { |
123 | MetadataManager manager = MetadataLocator.getMetadataManager(); |
||
124 | if (manager.getDefinition(METADATA_DEFINITION_NAME) == null) { |
||
125 | manager.addDefinition( |
||
126 | METADATA_DEFINITION_NAME, |
||
127 | DBFStoreParameters.class.getResourceAsStream("DBFStoreMetadata.xml"),
|
||
128 | DBFStoreParameters.class.getClassLoader() |
||
129 | ); |
||
130 | } |
||
131 | } |
||
132 | 40435 | jjdelcerro | |
133 | 41483 | jjdelcerro | public DBFStoreProvider(DBFStoreParameters params,
|
134 | DataStoreProviderServices storeServices) |
||
135 | throws InitializeException {
|
||
136 | 44840 | jjdelcerro | this(
|
137 | 41483 | jjdelcerro | params, |
138 | storeServices, |
||
139 | FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME) |
||
140 | ); |
||
141 | } |
||
142 | 40435 | jjdelcerro | |
143 | 41483 | jjdelcerro | protected DBFStoreProvider(DBFStoreParameters params,
|
144 | DataStoreProviderServices storeServices, DynObject metadata) |
||
145 | throws InitializeException {
|
||
146 | super(params, storeServices, metadata);
|
||
147 | 44840 | jjdelcerro | this.logger = new FilteredLogger(LOG, "DBFStoreProvider", -1); |
148 | 46607 | fdiaz | this.logger.setInterval(2000L); |
149 | 41483 | jjdelcerro | this.init(params, storeServices);
|
150 | } |
||
151 | 40435 | jjdelcerro | |
152 | 41483 | jjdelcerro | protected void init(DBFStoreParameters params, |
153 | DataStoreProviderServices storeServices) throws InitializeException {
|
||
154 | if (params == null) { |
||
155 | throw new InitializeException(new NullPointerException("params is null")); |
||
156 | } |
||
157 | File theFile = getDBFParameters().getDBFFile();
|
||
158 | if (theFile == null) { |
||
159 | throw new InitializeException(new NullPointerException("dbf file is null")); |
||
160 | } |
||
161 | initResource(params, storeServices); |
||
162 | 40435 | jjdelcerro | |
163 | 41483 | jjdelcerro | Charset charset = params.getEncoding();
|
164 | 42814 | fdiaz | allowDuplicatedFieldNames = params.allowDuplicatedFieldNames(); |
165 | this.dbfFile = new DbaseFile(theFile, charset, allowDuplicatedFieldNames); |
||
166 | 40435 | jjdelcerro | |
167 | 41483 | jjdelcerro | writer = new DBFFeatureWriter(this.getProviderName()); |
168 | 40435 | jjdelcerro | |
169 | 41483 | jjdelcerro | this.initFeatureType();
|
170 | 40435 | jjdelcerro | |
171 | 41483 | jjdelcerro | } |
172 | 40435 | jjdelcerro | |
173 | 41483 | jjdelcerro | public Object getDynValue(String name) throws DynFieldNotFoundException { |
174 | try {
|
||
175 | this.open();
|
||
176 | } catch (OpenException e) {
|
||
177 | throw new RuntimeException(e); |
||
178 | } |
||
179 | 42517 | dmartinezizquierdo | |
180 | 41483 | jjdelcerro | if (METADATA_ENCODING.equalsIgnoreCase(name)) {
|
181 | return this.dbfFile.getOriginalCharset(); |
||
182 | } else if (METADATA_CODEPAGE.equalsIgnoreCase(name)) { |
||
183 | 44669 | jjdelcerro | return this.dbfFile.getCodePageInt(); |
184 | 41483 | jjdelcerro | } |
185 | return super.getDynValue(name); |
||
186 | } |
||
187 | 40435 | jjdelcerro | |
188 | 41483 | jjdelcerro | protected void initResource(DBFStoreParameters params, |
189 | DataStoreProviderServices storeServices) throws InitializeException {
|
||
190 | 40435 | jjdelcerro | |
191 | 41483 | jjdelcerro | File theFile = getDBFParameters().getDBFFile();
|
192 | dbfResource |
||
193 | = this.createResource(FileResource.NAME,
|
||
194 | new Object[]{theFile.getAbsolutePath()}); |
||
195 | dbfResource.addConsumer(this);
|
||
196 | } |
||
197 | 40435 | jjdelcerro | |
198 | 42814 | fdiaz | protected void initResource(ResourceProvider resource, |
199 | DataStoreProviderServices storeServices){ |
||
200 | dbfResource = resource; |
||
201 | dbfResource.addConsumer(this);
|
||
202 | } |
||
203 | |||
204 | 41483 | jjdelcerro | public String getProviderName() { |
205 | return NAME;
|
||
206 | } |
||
207 | 40435 | jjdelcerro | |
208 | 41483 | jjdelcerro | protected DBFStoreParameters getDBFParameters() {
|
209 | return (DBFStoreParameters) super.getParameters(); |
||
210 | } |
||
211 | 40435 | jjdelcerro | |
212 | 41483 | jjdelcerro | public DataServerExplorer getExplorer() throws ReadException { |
213 | DataManager manager = DALLocator.getDataManager(); |
||
214 | FilesystemServerExplorerParameters params; |
||
215 | try {
|
||
216 | params = (FilesystemServerExplorerParameters) manager |
||
217 | .createServerExplorerParameters(FilesystemServerExplorer.NAME); |
||
218 | params.setRoot(this.getDBFParameters().getDBFFile().getParent());
|
||
219 | return manager.openServerExplorer(FilesystemServerExplorer.NAME, params);
|
||
220 | 44669 | jjdelcerro | } catch (DataException | ValidateDataParametersException e) {
|
221 | 42811 | jjdelcerro | throw new ReadException(this.getName(), e); |
222 | 41483 | jjdelcerro | } |
223 | } |
||
224 | 40435 | jjdelcerro | |
225 | 41483 | jjdelcerro | protected FeatureProvider internalGetFeatureProviderByReference(
|
226 | FeatureReferenceProviderServices reference, FeatureType featureType) |
||
227 | throws DataException {
|
||
228 | return this.getFeatureProviderByIndex( |
||
229 | 43356 | fdiaz | ((Number) reference.getOID()).longValue(), featureType);
|
230 | 41483 | jjdelcerro | } |
231 | 40435 | jjdelcerro | |
232 | 41483 | jjdelcerro | public void performChanges(Iterator deleteds, Iterator inserteds, |
233 | Iterator updateds, Iterator originalFeatureTypesUpdated) |
||
234 | throws PerformEditingException {
|
||
235 | 40435 | jjdelcerro | |
236 | 41483 | jjdelcerro | /*
|
237 | * This will throw an exception if there are new fields
|
||
238 | * with names too long
|
||
239 | */
|
||
240 | checkNewFieldsNameSize(originalFeatureTypesUpdated); |
||
241 | 40435 | jjdelcerro | |
242 | 41483 | jjdelcerro | try {
|
243 | 42517 | dmartinezizquierdo | // TODO repasar el concepto de enUso de un recurso.
|
244 | loTengoEnUso = true;
|
||
245 | 44669 | jjdelcerro | final FeatureStore theStore = this.getStoreServices().getFeatureStore(); |
246 | 42517 | dmartinezizquierdo | resourceCloseRequest(); |
247 | 41483 | jjdelcerro | getResource().execute(new ResourceAction() {
|
248 | 40435 | jjdelcerro | |
249 | 41483 | jjdelcerro | public Object run() throws Exception { |
250 | FeatureSet set = null;
|
||
251 | DisposableIterator iter = null;
|
||
252 | try {
|
||
253 | 44669 | jjdelcerro | set = theStore.getFeatureSet(); |
254 | 41483 | jjdelcerro | DBFStoreParameters tmpParams |
255 | = (DBFStoreParameters) getDBFParameters().getCopy(); |
||
256 | 40435 | jjdelcerro | |
257 | 41483 | jjdelcerro | File tmp_file = File.createTempFile( |
258 | "tmp_" + System.currentTimeMillis(), ".dbf"); |
||
259 | tmp_file.deleteOnExit(); |
||
260 | 40435 | jjdelcerro | |
261 | 41483 | jjdelcerro | tmpParams.setDBFFile(tmp_file); |
262 | 40435 | jjdelcerro | |
263 | 44669 | jjdelcerro | writer.begin(tmpParams, theStore.getDefaultFeatureType(), |
264 | 41483 | jjdelcerro | set.getSize()); |
265 | 40435 | jjdelcerro | |
266 | 41483 | jjdelcerro | iter = set.fastIterator(); |
267 | while (iter.hasNext()) {
|
||
268 | Feature feature = (Feature) iter.next(); |
||
269 | writer.append(feature); |
||
270 | } |
||
271 | 40435 | jjdelcerro | |
272 | 41483 | jjdelcerro | writer.end(); |
273 | 42517 | dmartinezizquierdo | loTengoEnUso = false;
|
274 | 41483 | jjdelcerro | try {
|
275 | close(); |
||
276 | } catch (CloseException e1) {
|
||
277 | throw new PerformEditingException(getProviderName(), e1); |
||
278 | } |
||
279 | getDBFParameters().getDBFFile().delete(); |
||
280 | 40435 | jjdelcerro | |
281 | 41483 | jjdelcerro | File target_file = getDBFParameters().getDBFFile();
|
282 | if (target_file.exists()) {
|
||
283 | target_file.delete(); |
||
284 | } |
||
285 | tmp_file.renameTo(target_file); |
||
286 | 40435 | jjdelcerro | |
287 | 41483 | jjdelcerro | if (tmp_file.exists() && !target_file.exists()) {
|
288 | // Renaming failed, let's simply copy.
|
||
289 | // We assume we cannot delete it, but we
|
||
290 | // used deleteOnExit and it's
|
||
291 | // temporary, so no problem
|
||
292 | LOG.info("Warning: copying tmp file instead of renaming: "
|
||
293 | + target_file.getName()); |
||
294 | FileUtils.copyFile(tmp_file, target_file); |
||
295 | } |
||
296 | 40435 | jjdelcerro | |
297 | 41483 | jjdelcerro | resourcesNotifyChanges(); |
298 | initFeatureType(); |
||
299 | } finally {
|
||
300 | 42517 | dmartinezizquierdo | loTengoEnUso = false;
|
301 | 41483 | jjdelcerro | if (set != null) { |
302 | set.dispose(); |
||
303 | } |
||
304 | if (iter != null) { |
||
305 | iter.dispose(); |
||
306 | } |
||
307 | } |
||
308 | return null; |
||
309 | } |
||
310 | }); |
||
311 | 42517 | dmartinezizquierdo | } catch (ResourceExecuteException | ResourceException e) {
|
312 | 44669 | jjdelcerro | throw new PerformEditingException(NAME, e); |
313 | 41483 | jjdelcerro | } |
314 | 40435 | jjdelcerro | |
315 | 41483 | jjdelcerro | this.counterNewsOIDs = -1; |
316 | } |
||
317 | 40435 | jjdelcerro | |
318 | 41483 | jjdelcerro | protected void checkNewFieldsNameSize(Iterator ft_upd) throws PerformEditingException { |
319 | 40435 | jjdelcerro | |
320 | 41483 | jjdelcerro | String long_fields = getNewFieldsWithNameTooLong(ft_upd);
|
321 | if (long_fields != null) { |
||
322 | AttributeNameException ane = new AttributeNameTooLongException(
|
||
323 | long_fields, |
||
324 | getProviderName(), |
||
325 | MAX_FIELD_NAME_LENGTH); |
||
326 | throw new PerformEditingException(getProviderName(), ane); |
||
327 | } |
||
328 | } |
||
329 | 40435 | jjdelcerro | |
330 | 41483 | jjdelcerro | /**
|
331 | * Returns null or a string which is a comma-separated list
|
||
332 | *
|
||
333 | * @param ft_updated
|
||
334 | * @return
|
||
335 | */
|
||
336 | protected String getNewFieldsWithNameTooLong(Iterator ft_updated) { |
||
337 | 40435 | jjdelcerro | |
338 | 41483 | jjdelcerro | String resp = ""; |
339 | 44669 | jjdelcerro | FeatureTypeChanged item; |
340 | FeatureType ft; |
||
341 | FeatureAttributeDescriptor[] atts;
|
||
342 | 41483 | jjdelcerro | while (ft_updated.hasNext()) {
|
343 | item = (FeatureTypeChanged) ft_updated.next(); |
||
344 | ft = item.getTarget(); |
||
345 | atts = ft.getAttributeDescriptors(); |
||
346 | 44669 | jjdelcerro | for (FeatureAttributeDescriptor att : atts) {
|
347 | if (att.getName().length() > MAX_FIELD_NAME_LENGTH) {
|
||
348 | 41483 | jjdelcerro | if (resp.length() == 0) { |
349 | 44669 | jjdelcerro | resp = att.getName(); |
350 | 41483 | jjdelcerro | } else {
|
351 | 44669 | jjdelcerro | resp = resp + ", " + att.getName();
|
352 | 41483 | jjdelcerro | } |
353 | } |
||
354 | } |
||
355 | } |
||
356 | 40435 | jjdelcerro | |
357 | 41483 | jjdelcerro | if (resp.length() == 0) { |
358 | return null; |
||
359 | } else {
|
||
360 | return "(" + resp + ")"; |
||
361 | } |
||
362 | } |
||
363 | 40435 | jjdelcerro | |
364 | 41483 | jjdelcerro | public FeatureProvider createFeatureProvider(FeatureType type) throws DataException { |
365 | return new DBFFeatureProvider(this, type); |
||
366 | } |
||
367 | 40435 | jjdelcerro | |
368 | 41483 | jjdelcerro | protected void initFeatureType() throws InitializeException { |
369 | 46897 | fdiaz | this.featureType = this.getTheFeatureType(); |
370 | FeatureType defaultType = this.featureType.getNotEditableCopy();
|
||
371 | this.setStoreFeatureType(defaultType);
|
||
372 | 41483 | jjdelcerro | } |
373 | 40435 | jjdelcerro | |
374 | 46897 | fdiaz | protected void setStoreFeatureType(FeatureType ftype) { |
375 | 45387 | omartinez | FeatureStoreProviderServices store = this.getStoreServices();
|
376 | List<FeatureType> ftypes = new ArrayList<>(); |
||
377 | ftypes.add(ftype); |
||
378 | store.setFeatureTypes(ftypes, ftype); |
||
379 | } |
||
380 | |||
381 | 44669 | jjdelcerro | protected EditableFeatureType getTheFeatureType() throws InitializeException { |
382 | 41483 | jjdelcerro | try {
|
383 | this.open();
|
||
384 | } catch (DataException e) {
|
||
385 | throw new InitializeException(this.getProviderName(), e); |
||
386 | } |
||
387 | 44669 | jjdelcerro | EditableFeatureType featureType = (EditableFeatureType) getResource().execute( |
388 | new ResourceAction() {
|
||
389 | public Object run() throws Exception { |
||
390 | EditableFeatureType featureType = getStoreServices().createFeatureType(getName()); |
||
391 | featureType.setHasOID(true);
|
||
392 | dbfFile.getHeader().toFeatureType( |
||
393 | featureType, |
||
394 | getDBFParameters().handleDatesAsStrings() |
||
395 | ); |
||
396 | return featureType;
|
||
397 | 41483 | jjdelcerro | } |
398 | 44669 | jjdelcerro | } |
399 | 41483 | jjdelcerro | ); |
400 | 44669 | jjdelcerro | return featureType;
|
401 | 41483 | jjdelcerro | } |
402 | 44669 | jjdelcerro | |
403 | |||
404 | 44001 | omartinez | protected void loadValue(FeatureProvider featureProvider, long rowIndex, |
405 | 41483 | jjdelcerro | FeatureAttributeDescriptor descriptor) throws ReadException {
|
406 | 40435 | jjdelcerro | |
407 | 41483 | jjdelcerro | if (descriptor.getEvaluator() != null) { |
408 | // Nothing to do
|
||
409 | return;
|
||
410 | } |
||
411 | 40435 | jjdelcerro | |
412 | 44669 | jjdelcerro | int dbfFieldIndex = this.dbfFile.getFieldIndex(descriptor.getName()); |
413 | 40435 | jjdelcerro | |
414 | 44669 | jjdelcerro | if (dbfFieldIndex < 0) { |
415 | 41483 | jjdelcerro | // Someone asked to load a field
|
416 | 42517 | dmartinezizquierdo | // which does not exist in the DBF file. This can happen
|
417 | 41483 | jjdelcerro | // in editing process when a field has been added
|
418 | // in the current editing session, so we simply do nothing.
|
||
419 | // The expansion manager is expected to manage those new fields
|
||
420 | // and their values.
|
||
421 | 44669 | jjdelcerro | this.logger.warn("The requested field ("+descriptor.getName()+") does not exist in the DBF file. Assumed it's a new field in editing mode."); |
422 | 41483 | jjdelcerro | return;
|
423 | } |
||
424 | 40435 | jjdelcerro | |
425 | 41483 | jjdelcerro | String value = null; |
426 | try {
|
||
427 | 44669 | jjdelcerro | value = this.dbfFile.getStringFieldValue(rowIndex, dbfFieldIndex);
|
428 | 41483 | jjdelcerro | } catch (DataException e) {
|
429 | 42811 | jjdelcerro | throw new ReadException(this.getName(), e); |
430 | 41483 | jjdelcerro | } |
431 | value = value.trim(); |
||
432 | 44669 | jjdelcerro | FieldFormatter formatter = new FieldFormatter();
|
433 | |||
434 | int index = descriptor.getIndex();
|
||
435 | Object defaultValue = descriptor.getDefaultValueCoerced();
|
||
436 | |||
437 | switch (descriptor.getType()) {
|
||
438 | 41483 | jjdelcerro | case DataTypes.STRING:
|
439 | 44669 | jjdelcerro | featureProvider.set(index, formatter.parseString(value, (String) defaultValue));
|
440 | 41483 | jjdelcerro | break;
|
441 | 40435 | jjdelcerro | |
442 | 44669 | jjdelcerro | case DataTypes.DECIMAL:
|
443 | featureProvider.set(index, |
||
444 | formatter.parseDecimal( |
||
445 | value, |
||
446 | descriptor.getMathContext(), |
||
447 | descriptor.getScale(), |
||
448 | (BigDecimal) defaultValue
|
||
449 | ) |
||
450 | ); |
||
451 | 41483 | jjdelcerro | break;
|
452 | 40435 | jjdelcerro | |
453 | 44669 | jjdelcerro | case DataTypes.DOUBLE:
|
454 | featureProvider.set(index, formatter.parseDouble(value, (Double) defaultValue));
|
||
455 | 41483 | jjdelcerro | break;
|
456 | 40435 | jjdelcerro | |
457 | 41483 | jjdelcerro | case DataTypes.FLOAT:
|
458 | 44669 | jjdelcerro | featureProvider.set(index, formatter.parseFloat(value, (Float) defaultValue));
|
459 | 41483 | jjdelcerro | break;
|
460 | 40435 | jjdelcerro | |
461 | 41483 | jjdelcerro | case DataTypes.LONG:
|
462 | 44669 | jjdelcerro | featureProvider.set(index, formatter.parseLong(value, (Long) defaultValue));
|
463 | 41483 | jjdelcerro | break;
|
464 | 40435 | jjdelcerro | |
465 | 44669 | jjdelcerro | case DataTypes.INT:
|
466 | featureProvider.set(index, formatter.parseInt(value, (Integer) defaultValue));
|
||
467 | 41483 | jjdelcerro | break;
|
468 | 40435 | jjdelcerro | |
469 | 41483 | jjdelcerro | case DataTypes.BYTE:
|
470 | 44669 | jjdelcerro | featureProvider.set(index, formatter.parseByte(value, (Byte) defaultValue));
|
471 | 41483 | jjdelcerro | break;
|
472 | 40435 | jjdelcerro | |
473 | 44669 | jjdelcerro | case DataTypes.BOOLEAN:
|
474 | featureProvider.set(index, formatter.parseBoolean(value, (Boolean) defaultValue));
|
||
475 | break;
|
||
476 | |||
477 | case DataTypes.TIMESTAMP:
|
||
478 | 44767 | jjdelcerro | featureProvider.set(index, formatter.parseTimestamp(value, (java.sql.Timestamp) defaultValue)); |
479 | 44669 | jjdelcerro | break;
|
480 | |||
481 | case DataTypes.TIME:
|
||
482 | 44767 | jjdelcerro | featureProvider.set(index, formatter.parseTime(value, (java.sql.Time) defaultValue)); |
483 | 44669 | jjdelcerro | break;
|
484 | |||
485 | 41483 | jjdelcerro | case DataTypes.DATE:
|
486 | 44767 | jjdelcerro | featureProvider.set(index, formatter.parseDate(value, (java.sql.Date) defaultValue)); |
487 | 41483 | jjdelcerro | break;
|
488 | 40435 | jjdelcerro | |
489 | 44472 | jjdelcerro | default: {
|
490 | Object v;
|
||
491 | try {
|
||
492 | v = descriptor.getDataType().coerce(value); |
||
493 | } catch (CoercionException ex) {
|
||
494 | 44669 | jjdelcerro | v = defaultValue; |
495 | 44472 | jjdelcerro | } |
496 | 44669 | jjdelcerro | featureProvider.set(index, v); |
497 | 44472 | jjdelcerro | } |
498 | 41483 | jjdelcerro | break;
|
499 | } |
||
500 | } |
||
501 | 40435 | jjdelcerro | |
502 | 41483 | jjdelcerro | protected FeatureProvider getFeatureProviderByIndex(long index) throws DataException { |
503 | return this |
||
504 | .getFeatureProviderByIndex(index, this.getStoreServices()
|
||
505 | .getDefaultFeatureType()); |
||
506 | } |
||
507 | 40435 | jjdelcerro | |
508 | 41483 | jjdelcerro | public long getFeatureCount() throws ReadException, OpenException, |
509 | ResourceNotifyChangesException { |
||
510 | this.open();
|
||
511 | 44669 | jjdelcerro | return (long) getResource().execute(new ResourceAction() { |
512 | 41483 | jjdelcerro | public Object run() throws Exception { |
513 | 44669 | jjdelcerro | return (long) dbfFile.getRecordCount(); |
514 | 41483 | jjdelcerro | } |
515 | 44669 | jjdelcerro | }); |
516 | 41483 | jjdelcerro | } |
517 | 40435 | jjdelcerro | |
518 | 41483 | jjdelcerro | public FeatureSetProvider createSet(FeatureQuery query, FeatureType featureType)
|
519 | throws DataException {
|
||
520 | return new DBFSetProvider(this, query, featureType); |
||
521 | } |
||
522 | 40435 | jjdelcerro | |
523 | 41483 | jjdelcerro | public boolean canCreate() { |
524 | return true; |
||
525 | } |
||
526 | 40435 | jjdelcerro | |
527 | 41483 | jjdelcerro | public boolean canWriteGeometry(int geometryType, int geometrySubType) throws DataException { |
528 | return false; |
||
529 | } |
||
530 | 40435 | jjdelcerro | |
531 | 41483 | jjdelcerro | public void open() throws OpenException { |
532 | if (this.dbfFile.isOpen()) { |
||
533 | return;
|
||
534 | } |
||
535 | try {
|
||
536 | getResource().execute(new ResourceAction() {
|
||
537 | public Object run() throws Exception { |
||
538 | openFile(); |
||
539 | resourcesOpen(); |
||
540 | return null; |
||
541 | } |
||
542 | }); |
||
543 | 40435 | jjdelcerro | |
544 | 41483 | jjdelcerro | } catch (ResourceExecuteException e) {
|
545 | throw new OpenException(this.getProviderName(), e); |
||
546 | } |
||
547 | } |
||
548 | 40435 | jjdelcerro | |
549 | 41483 | jjdelcerro | protected void openFile() throws FileNotFoundException, |
550 | UnsupportedVersionException, IOException, DataException {
|
||
551 | this.dbfFile.open();
|
||
552 | 43245 | jjdelcerro | // necessary when editing the file
|
553 | this.getDBFParameters().setEffectiveEncoding(this.dbfFile.getCharsetName()); |
||
554 | 41483 | jjdelcerro | } |
555 | 40435 | jjdelcerro | |
556 | 41483 | jjdelcerro | public void close() throws CloseException { |
557 | 42517 | dmartinezizquierdo | if( loTengoEnUso ) {
|
558 | return;
|
||
559 | } |
||
560 | 41483 | jjdelcerro | if (dbfFile == null || !this.dbfFile.isOpen()) { |
561 | return;
|
||
562 | } |
||
563 | super.close();
|
||
564 | 42517 | dmartinezizquierdo | |
565 | 41483 | jjdelcerro | //Cerrar recurso
|
566 | try {
|
||
567 | getResource().execute(new ResourceAction() {
|
||
568 | public Object run() throws Exception { |
||
569 | closeFile(); |
||
570 | resourcesNotifyClose(); |
||
571 | return null; |
||
572 | } |
||
573 | }); |
||
574 | 42517 | dmartinezizquierdo | } catch (ResourceExecuteException e) {
|
575 | 41483 | jjdelcerro | throw new CloseException(this.getProviderName(), e); |
576 | } |
||
577 | } |
||
578 | |||
579 | protected void closeFile() throws CloseException { |
||
580 | this.dbfFile.close();
|
||
581 | } |
||
582 | |||
583 | @Override
|
||
584 | protected void doDispose() throws BaseException { |
||
585 | this.close();
|
||
586 | dbfFile = null;
|
||
587 | disposeResource(); |
||
588 | super.doDispose();
|
||
589 | } |
||
590 | |||
591 | protected void disposeResource() { |
||
592 | this.dbfResource.removeConsumer(this); |
||
593 | dbfResource = null;
|
||
594 | } |
||
595 | |||
596 | public boolean closeResourceRequested(ResourceProvider resource) { |
||
597 | try {
|
||
598 | this.close();
|
||
599 | } catch (CloseException e) {
|
||
600 | return false; |
||
601 | } |
||
602 | return true; |
||
603 | } |
||
604 | |||
605 | public boolean allowWrite() { |
||
606 | 42814 | fdiaz | if(allowDuplicatedFieldNames){
|
607 | 41483 | jjdelcerro | return false; |
608 | } |
||
609 | 42814 | fdiaz | return this.dbfFile.isWritable(); |
610 | 41483 | jjdelcerro | } |
611 | |||
612 | public void refresh() throws OpenException { |
||
613 | try {
|
||
614 | this.close();
|
||
615 | } catch (CloseException e) {
|
||
616 | throw new OpenException(this.getProviderName(), e); |
||
617 | } |
||
618 | this.open();
|
||
619 | try {
|
||
620 | this.initFeatureType();
|
||
621 | } catch (InitializeException e) {
|
||
622 | throw new OpenException(this.getProviderName(), e); |
||
623 | } |
||
624 | } |
||
625 | |||
626 | /**
|
||
627 | *
|
||
628 | * @param index
|
||
629 | * @param featureType
|
||
630 | * @return
|
||
631 | * @throws ReadException
|
||
632 | */
|
||
633 | protected FeatureProvider getFeatureProviderByIndex(long index, |
||
634 | FeatureType featureType) throws DataException {
|
||
635 | FeatureProvider featureProvider = this.createFeatureProvider(featureType);
|
||
636 | 44669 | jjdelcerro | featureProvider.setOID(index); |
637 | 41483 | jjdelcerro | return featureProvider;
|
638 | } |
||
639 | |||
640 | protected void initFeatureProviderByIndex(FeatureProvider featureProvider, |
||
641 | long index, FeatureType featureType) throws DataException { |
||
642 | 44669 | jjdelcerro | featureProvider.setOID(index); |
643 | 41483 | jjdelcerro | } |
644 | |||
645 | /**
|
||
646 | *
|
||
647 | * @param featureProvider
|
||
648 | * @throws DataException
|
||
649 | */
|
||
650 | protected void loadFeatureProviderByIndex(FeatureProvider featureProvider) |
||
651 | throws DataException {
|
||
652 | |||
653 | 44001 | omartinez | long index = ((Long) featureProvider.getOID()); |
654 | 40435 | jjdelcerro | int rec_count = this.dbfFile.getRecordCount(); |
655 | 41483 | jjdelcerro | |
656 | 40435 | jjdelcerro | if (index >= rec_count) {
|
657 | |||
658 | 42811 | jjdelcerro | ReadException rex = new ReadException(this.getName(), |
659 | 41483 | jjdelcerro | new ArrayIndexOutOfBoundsException( |
660 | "Index of requested feature ("
|
||
661 | + index + ") is >= record count (" + rec_count + ")")); |
||
662 | |||
663 | 40435 | jjdelcerro | LOG.info("Error while loading feature. ", rex);
|
664 | throw rex;
|
||
665 | 41483 | jjdelcerro | } |
666 | 40435 | jjdelcerro | |
667 | 44669 | jjdelcerro | for (FeatureAttributeDescriptor desc : featureProvider.getType()) {
|
668 | this.loadValue(featureProvider, index, desc);
|
||
669 | 41483 | jjdelcerro | } |
670 | } |
||
671 | 40435 | jjdelcerro | |
672 | 41483 | jjdelcerro | public int getOIDType() { |
673 | return DataTypes.LONG;
|
||
674 | } |
||
675 | 40435 | jjdelcerro | |
676 | 41483 | jjdelcerro | public Object createNewOID() { |
677 | if (this.counterNewsOIDs < 0) { |
||
678 | try {
|
||
679 | this.counterNewsOIDs = this.getFeatureCount(); |
||
680 | } catch (DataException e) {
|
||
681 | 44669 | jjdelcerro | LOG.warn("Can't initialice counter for news OIDs.",e);
|
682 | 41483 | jjdelcerro | } |
683 | 40435 | jjdelcerro | |
684 | 41483 | jjdelcerro | } else {
|
685 | this.counterNewsOIDs++;
|
||
686 | } |
||
687 | 44669 | jjdelcerro | return counterNewsOIDs;
|
688 | 41483 | jjdelcerro | } |
689 | 40435 | jjdelcerro | |
690 | 41483 | jjdelcerro | public boolean supportsAppendMode() { |
691 | return true; |
||
692 | } |
||
693 | 40435 | jjdelcerro | |
694 | 41483 | jjdelcerro | public void append(final FeatureProvider featureProvider) |
695 | throws DataException {
|
||
696 | getResource().execute(new ResourceAction() {
|
||
697 | public Object run() throws Exception { |
||
698 | writer.append(getStoreServices().createFeature(featureProvider)); |
||
699 | return null; |
||
700 | } |
||
701 | }); |
||
702 | } |
||
703 | 40435 | jjdelcerro | |
704 | 41483 | jjdelcerro | public void beginAppend() throws DataException { |
705 | this.close();
|
||
706 | getResource().execute(new ResourceAction() {
|
||
707 | public Object run() throws Exception { |
||
708 | writer.begin(getDBFParameters(), |
||
709 | getStoreServices().getDefaultFeatureType(), |
||
710 | getStoreServices().getFeatureStore().getFeatureCount()); |
||
711 | return null; |
||
712 | } |
||
713 | }); |
||
714 | } |
||
715 | 40435 | jjdelcerro | |
716 | 41483 | jjdelcerro | public void endAppend() throws DataException { |
717 | getResource().execute(new ResourceAction() {
|
||
718 | public Object run() throws Exception { |
||
719 | writer.end(); |
||
720 | resourcesNotifyChanges(); |
||
721 | counterNewsOIDs = -1;
|
||
722 | return null; |
||
723 | } |
||
724 | }); |
||
725 | } |
||
726 | 40435 | jjdelcerro | |
727 | 41483 | jjdelcerro | public void resourceChanged(ResourceProvider resource) { |
728 | 42625 | dmartinezizquierdo | if (this.getStoreServices()!=null){ |
729 | this.getStoreServices().notifyChange(
|
||
730 | DataStoreNotification.RESOURCE_CHANGED, |
||
731 | resource); |
||
732 | } |
||
733 | 41483 | jjdelcerro | } |
734 | 40435 | jjdelcerro | |
735 | 41483 | jjdelcerro | /**
|
736 | *
|
||
737 | * @throws ResourceNotifyChangesException
|
||
738 | */
|
||
739 | protected void resourcesNotifyChanges() |
||
740 | throws ResourceNotifyChangesException {
|
||
741 | this.dbfResource.notifyChanges();
|
||
742 | } |
||
743 | 40435 | jjdelcerro | |
744 | 41483 | jjdelcerro | /**
|
745 | * @throws ResourceNotifyCloseException
|
||
746 | *
|
||
747 | */
|
||
748 | protected void resourcesNotifyClose() throws ResourceNotifyCloseException { |
||
749 | this.dbfResource.notifyClose();
|
||
750 | } |
||
751 | 40435 | jjdelcerro | |
752 | 41483 | jjdelcerro | /**
|
753 | * @throws ResourceNotifyOpenException
|
||
754 | *
|
||
755 | */
|
||
756 | protected void resourcesOpen() throws ResourceNotifyOpenException { |
||
757 | this.dbfResource.notifyOpen();
|
||
758 | } |
||
759 | 40435 | jjdelcerro | |
760 | 41483 | jjdelcerro | public Object getSourceId() { |
761 | return this.getDBFParameters().getFile(); |
||
762 | } |
||
763 | 40435 | jjdelcerro | |
764 | 41483 | jjdelcerro | public String getName() { |
765 | String name = this.getDBFParameters().getFile().getName(); |
||
766 | int n = name.lastIndexOf("."); |
||
767 | if (n < 1) { |
||
768 | return name;
|
||
769 | } |
||
770 | return name.substring(0, n); |
||
771 | } |
||
772 | 40435 | jjdelcerro | |
773 | 41483 | jjdelcerro | public String getFullName() { |
774 | return this.getDBFParameters().getFile().getAbsolutePath(); |
||
775 | } |
||
776 | |||
777 | protected void resourceCloseRequest() throws ResourceException { |
||
778 | this.dbfResource.closeRequest();
|
||
779 | } |
||
780 | |||
781 | public ResourceProvider getResource() {
|
||
782 | return dbfResource;
|
||
783 | } |
||
784 | 45387 | omartinez | |
785 | @Override
|
||
786 | public void fixFeatureTypeFromParameters() { |
||
787 | FeatureStoreProviderServices store = this.getStoreServices();
|
||
788 | try {
|
||
789 | int sizeWithoutComputed = 0; |
||
790 | for (FeatureAttributeDescriptor featureAttributeDescriptor : store.getDefaultFeatureType()) {
|
||
791 | if (featureAttributeDescriptor.isComputed()) {
|
||
792 | continue;
|
||
793 | } |
||
794 | sizeWithoutComputed +=1;
|
||
795 | } |
||
796 | if(this.featureType.size()!=sizeWithoutComputed) { |
||
797 | 46897 | fdiaz | this.setStoreFeatureType(featureType.getNotEditableCopy());
|
798 | 45387 | omartinez | } |
799 | } catch (DataException ex) {
|
||
800 | |||
801 | } |
||
802 | } |
||
803 | 43245 | jjdelcerro | |
804 | 41483 | jjdelcerro | } |