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.lib / src / main / java / org / gvsig / fmap / dal / feature / spi / simpleprovider / AutomaticDetectionOfTypes.java @ 44669
History | View | Annotate | Download (8.45 KB)
1 |
package org.gvsig.fmap.dal.feature.spi.simpleprovider; |
---|---|
2 |
|
3 |
import java.io.IOException; |
4 |
import java.net.URL; |
5 |
import java.util.ArrayList; |
6 |
import java.util.List; |
7 |
import java.util.Locale; |
8 |
import java.util.Objects; |
9 |
import org.gvsig.fmap.dal.DataTypes; |
10 |
import org.gvsig.tools.ToolsLocator; |
11 |
import org.gvsig.tools.dataTypes.Coercion; |
12 |
import org.gvsig.tools.dataTypes.CoercionContext; |
13 |
import org.gvsig.tools.dataTypes.DataTypeUtils; |
14 |
import org.gvsig.tools.dataTypes.DataTypesManager; |
15 |
|
16 |
/**
|
17 |
*
|
18 |
* @author jjdelcerro
|
19 |
*/
|
20 |
public class AutomaticDetectionOfTypes { |
21 |
|
22 |
public interface Rows { |
23 |
public List<Object> read(); |
24 |
} |
25 |
|
26 |
private static class PossibleDataType { |
27 |
|
28 |
public boolean possibleInt = true; |
29 |
public boolean possibleFloat = true; |
30 |
public boolean possibleDouble = true; |
31 |
public boolean possibleDecimal = true; |
32 |
public boolean possibleLong = true; |
33 |
public boolean possibleURL = true; |
34 |
public boolean possibleDate = true; |
35 |
public boolean possibleGeometry = true; |
36 |
} |
37 |
|
38 |
private final String filename; |
39 |
|
40 |
public AutomaticDetectionOfTypes() {
|
41 |
this("(unknown)"); |
42 |
} |
43 |
|
44 |
public AutomaticDetectionOfTypes(String filename) { |
45 |
this.filename = filename;
|
46 |
} |
47 |
|
48 |
private String getFullFileName() { |
49 |
return this.filename; |
50 |
} |
51 |
|
52 |
@SuppressWarnings({"UseSpecificCatch", "ResultOfObjectAllocationIgnored"}) |
53 |
public int[] detect(int columns, Rows rows, boolean isFirstLineHeader, Locale locale) throws IOException { |
54 |
List<PossibleDataType> possibleDataTypes;
|
55 |
int[] types = null; |
56 |
|
57 |
int lineno = 0; |
58 |
try {
|
59 |
if (isFirstLineHeader) {
|
60 |
rows.read(); |
61 |
lineno++; |
62 |
} |
63 |
possibleDataTypes = new ArrayList<>(columns); |
64 |
for (int i = 0; i < columns; i++) { |
65 |
possibleDataTypes.add(new PossibleDataType());
|
66 |
} |
67 |
if (locale == null) { |
68 |
locale = Locale.getDefault();
|
69 |
} |
70 |
DataTypesManager typeManager = ToolsLocator.getDataTypesManager(); |
71 |
Coercion toDecimal = typeManager.getCoercion(DataTypes.DECIMAL); |
72 |
Coercion toDouble = typeManager.getCoercion(DataTypes.DOUBLE); |
73 |
Coercion toFloat = typeManager.getCoercion(DataTypes.FLOAT); |
74 |
Coercion toDate = typeManager.getCoercion(DataTypes.DATE); |
75 |
Coercion toInt = typeManager.getCoercion(DataTypes.INT); |
76 |
Coercion toLong = typeManager.getCoercion(DataTypes.LONG); |
77 |
Coercion toGeom = typeManager.getCoercion(DataTypes.GEOMETRY); |
78 |
CoercionContext coercionContext = DataTypeUtils.coerceContextLocale(locale); |
79 |
|
80 |
List<Object> row = rows.read(); |
81 |
lineno++; |
82 |
|
83 |
while (row != null) { |
84 |
for (int i = 0; i < row.size(); i++) { |
85 |
while( possibleDataTypes.size()<row.size() ) {
|
86 |
possibleDataTypes.add(new PossibleDataType());
|
87 |
} |
88 |
String rawvalue = Objects.toString(row.get(i),null); |
89 |
PossibleDataType possibleDataType = possibleDataTypes.get(i); |
90 |
if (possibleDataType.possibleDecimal) {
|
91 |
try {
|
92 |
toDecimal.coerce(rawvalue, coercionContext); |
93 |
possibleDataType.possibleDecimal = true;
|
94 |
} catch (Exception ex) { |
95 |
possibleDataType.possibleDecimal = false;
|
96 |
} |
97 |
} |
98 |
if (possibleDataType.possibleDouble) {
|
99 |
try {
|
100 |
toDouble.coerce(rawvalue, coercionContext); |
101 |
possibleDataType.possibleDouble = true;
|
102 |
} catch (Exception ex) { |
103 |
possibleDataType.possibleDouble = false;
|
104 |
} |
105 |
} |
106 |
if (possibleDataType.possibleFloat) {
|
107 |
try {
|
108 |
toFloat.coerce(rawvalue, coercionContext); |
109 |
possibleDataType.possibleFloat = true;
|
110 |
} catch (Exception ex) { |
111 |
possibleDataType.possibleFloat = false;
|
112 |
} |
113 |
} |
114 |
if (possibleDataType.possibleLong) {
|
115 |
possibleDataType.possibleLong = isValidLong(rawvalue); |
116 |
} |
117 |
if (possibleDataType.possibleInt) {
|
118 |
possibleDataType.possibleInt = isValidInteger(rawvalue); |
119 |
} |
120 |
if (possibleDataType.possibleDate) {
|
121 |
try {
|
122 |
toDate.coerce(rawvalue, coercionContext); |
123 |
possibleDataType.possibleDate = true;
|
124 |
} catch (Exception ex) { |
125 |
possibleDataType.possibleDate = false;
|
126 |
} |
127 |
} |
128 |
if (possibleDataType.possibleURL) {
|
129 |
try {
|
130 |
new URL((String) rawvalue); |
131 |
possibleDataType.possibleURL = true;
|
132 |
} catch (Exception ex) { |
133 |
possibleDataType.possibleURL = false;
|
134 |
} |
135 |
} |
136 |
if (possibleDataType.possibleGeometry) {
|
137 |
try {
|
138 |
toGeom.coerce((String) rawvalue);
|
139 |
possibleDataType.possibleGeometry = true;
|
140 |
} catch (Exception ex) { |
141 |
possibleDataType.possibleGeometry = false;
|
142 |
} |
143 |
} |
144 |
} |
145 |
row = rows.read(); |
146 |
} |
147 |
int n = 0; |
148 |
types = new int[possibleDataTypes.size()]; |
149 |
for (PossibleDataType possibleDataType : possibleDataTypes) {
|
150 |
if (possibleDataType.possibleInt) {
|
151 |
types[n++] = DataTypes.INT; |
152 |
continue;
|
153 |
} |
154 |
if (possibleDataType.possibleLong) {
|
155 |
types[n++] = DataTypes.LONG; |
156 |
continue;
|
157 |
} |
158 |
if (possibleDataType.possibleDecimal) {
|
159 |
types[n++] = DataTypes.DECIMAL; |
160 |
continue;
|
161 |
} |
162 |
if (possibleDataType.possibleFloat) {
|
163 |
// Forzamos los float a double para evitar perder precision
|
164 |
types[n++] = DataTypes.DOUBLE; |
165 |
continue;
|
166 |
} |
167 |
if (possibleDataType.possibleDouble) {
|
168 |
types[n++] = DataTypes.DOUBLE; |
169 |
continue;
|
170 |
} |
171 |
if (possibleDataType.possibleURL) {
|
172 |
types[n++] = DataTypes.URL; |
173 |
continue;
|
174 |
} |
175 |
if (possibleDataType.possibleDate) {
|
176 |
types[n++] = DataTypes.DATE; |
177 |
continue;
|
178 |
} |
179 |
if (possibleDataType.possibleGeometry) {
|
180 |
types[n++] = DataTypes.GEOMETRY; |
181 |
continue;
|
182 |
} |
183 |
types[n++] = DataTypes.STRING; |
184 |
} |
185 |
} catch (Exception ex) { |
186 |
throw new RuntimeException("Problems reading file '" + this.getFullFileName() + "' near line " + lineno + ".", ex); |
187 |
} |
188 |
return types;
|
189 |
} |
190 |
|
191 |
@SuppressWarnings("UseSpecificCatch") |
192 |
private boolean isValidLong(String s) { |
193 |
if (s == null) { |
194 |
return true; |
195 |
} |
196 |
s = s.trim().toLowerCase(); |
197 |
if (s.isEmpty()) {
|
198 |
return true; |
199 |
} |
200 |
try {
|
201 |
if (s.startsWith("0x")) { |
202 |
Long.valueOf(s.substring(2), 16); |
203 |
} else {
|
204 |
Long.valueOf(s);
|
205 |
} |
206 |
return true; |
207 |
} catch (Exception ex) { |
208 |
return false; |
209 |
} |
210 |
} |
211 |
|
212 |
@SuppressWarnings("UseSpecificCatch") |
213 |
private boolean isValidInteger(String s) { |
214 |
if (s == null) { |
215 |
return true; |
216 |
} |
217 |
s = s.trim().toLowerCase(); |
218 |
if (s.isEmpty()) {
|
219 |
return true; |
220 |
} |
221 |
try {
|
222 |
if (s.startsWith("0x")) { |
223 |
Integer.valueOf(s.substring(2), 16); |
224 |
} else {
|
225 |
Integer.valueOf(s);
|
226 |
} |
227 |
return true; |
228 |
} catch (Exception ex) { |
229 |
return false; |
230 |
} |
231 |
} |
232 |
|
233 |
} |