Revision 32521 trunk/extensions/extOracleSpatial/src/es/prodevelop/cit/gvsig/fmap/drivers/jdbc/oracle/OracleSpatialUtils.java
OracleSpatialUtils.java | ||
---|---|---|
54 | 54 |
import java.sql.Connection; |
55 | 55 |
import java.sql.PreparedStatement; |
56 | 56 |
import java.sql.ResultSet; |
57 |
import java.sql.ResultSetMetaData; |
|
57 | 58 |
import java.sql.SQLException; |
58 | 59 |
import java.sql.Types; |
59 | 60 |
import java.text.DecimalFormat; |
... | ... | |
87 | 88 |
import com.iver.cit.gvsig.fmap.core.FShape3D; |
88 | 89 |
import com.iver.cit.gvsig.fmap.core.GeneralPathX; |
89 | 90 |
import com.iver.cit.gvsig.fmap.core.IGeometry; |
91 |
import com.iver.cit.gvsig.fmap.core.IGeometry3D; |
|
92 |
import com.iver.cit.gvsig.fmap.core.IGeometryM; |
|
90 | 93 |
import com.iver.cit.gvsig.fmap.core.ShapeFactory; |
91 | 94 |
import com.iver.cit.gvsig.fmap.core.v02.FConverter; |
92 | 95 |
import com.iver.cit.gvsig.fmap.drivers.ConnectionJDBC; |
... | ... | |
127 | 130 |
public static final int ORACLE_GTYPE_MULTILINE = 6; |
128 | 131 |
public static final int ORACLE_GTYPE_MULTIPOLYGON = 7; |
129 | 132 |
|
130 |
public static final int ORACLE_GTYPE_COMPLEX_VOIDED_POLYON = 3;
|
|
133 |
public static final int ORACLE_GTYPE_COMPLEX_VOIDED_OR_NORMAL_POLYGON = 3;
|
|
131 | 134 |
public static final int ORACLE_GTYPE_COMPLEX_COMPOUND_LINE = 4; |
132 |
public static final int ORACLE_GTYPE_COMPLEX_COMPOUND_POLYON = 5; |
|
135 |
public static final int ORACLE_GTYPE_COMPLEX_COMPOUND_POLYGON = 5;
|
|
133 | 136 |
|
134 | 137 |
// req by wolfgang qual sept 2009 |
135 | 138 |
public static final String ORACLE_GEOM_METADATA_TOLERANCE = "0.0005"; |
139 |
public static final int FETCH_BLOCK_SIZE_BYTES = 50 * 1000 * 1000; |
|
136 | 140 |
|
141 |
|
|
137 | 142 |
/** |
138 | 143 |
* COnstructs a geometry from a file that contains a vertex per line: |
139 | 144 |
* |
... | ... | |
1678 | 1683 |
|
1679 | 1684 |
// String ind_str = printArray(indices); |
1680 | 1685 |
// String ord_str = printArray(ords); |
1686 |
// obj = getTestPolygon(); |
|
1681 | 1687 |
resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), obj); |
1682 | 1688 |
|
1683 | 1689 |
return resp; |
1684 | 1690 |
} |
1685 | 1691 |
|
1686 |
public static String printArray(NUMBER[] array) { |
|
1692 |
private static Object[] getTestPolygon(boolean b) throws SQLException { |
|
1693 |
|
|
1694 |
Object[] resp = new Object[5]; |
|
1695 |
resp[0] = new NUMBER(3005); |
|
1696 |
resp[1] = null; |
|
1697 |
|
|
1698 |
NUMBER[] _ind = new NUMBER[6]; |
|
1699 |
_ind[0] = new NUMBER(1.0); |
|
1700 |
_ind[1] = new NUMBER(2005.0); |
|
1701 |
_ind[2] = new NUMBER(1.0); |
|
1702 |
_ind[3] = new NUMBER(1.0); |
|
1703 |
_ind[4] = new NUMBER(2.0); |
|
1704 |
_ind[5] = new NUMBER(2.0); |
|
1705 |
|
|
1706 |
NUMBER[] _ord = new NUMBER[33]; |
|
1707 |
_ord[0] = new NUMBER(4478106.584); |
|
1708 |
_ord[1] = new NUMBER(5345524.3355); |
|
1709 |
_ord[2] = new NUMBER(0.0); |
|
1710 |
_ord[3] = new NUMBER(4478103.55781412); |
|
1711 |
_ord[4] = new NUMBER(5345520.13869913); |
|
1712 |
_ord[5] = new NUMBER(0.0); |
|
1713 |
_ord[6] = new NUMBER(4478094.627); |
|
1714 |
_ord[7] = new NUMBER(5345517.0485); |
|
1715 |
_ord[8] = new NUMBER(0.0 ); |
|
1716 |
_ord[9] = new NUMBER(4478088.31210806); |
|
1717 |
_ord[10] = new NUMBER(5345521.30429374); |
|
1718 |
_ord[11] = new NUMBER(0.0 ); |
|
1719 |
_ord[12] = new NUMBER(4478087.661); |
|
1720 |
_ord[13] = new NUMBER(5345528.8915); |
|
1721 |
_ord[14] = new NUMBER(0.0 ); |
|
1722 |
_ord[15] = new NUMBER(4478093.20816592); |
|
1723 |
_ord[16] = new NUMBER(5345537.22495391); |
|
1724 |
_ord[17] = new NUMBER(0.0 ); |
|
1725 |
_ord[18] = new NUMBER(4478103.219); |
|
1726 |
_ord[19] = new NUMBER(5345537.2515); |
|
1727 |
_ord[20] = new NUMBER(0.0 ); |
|
1728 |
_ord[21] = new NUMBER(4478107.61580098); |
|
1729 |
_ord[22] = new NUMBER(5345529.07024585); |
|
1730 |
_ord[23] = new NUMBER(0.0 ); |
|
1731 |
_ord[24] = new NUMBER(4478107.585); |
|
1732 |
_ord[25] = new NUMBER(5345528.688); |
|
1733 |
_ord[26] = new NUMBER(0.0 ); |
|
1734 |
_ord[27] = new NUMBER(4478107.28586386); |
|
1735 |
_ord[28] = new NUMBER(5345526.46542887); |
|
1736 |
_ord[29] = new NUMBER(0.0 ); |
|
1737 |
_ord[30] = new NUMBER(4478106.584); |
|
1738 |
_ord[31] = new NUMBER(5345524.3355); |
|
1739 |
_ord[32] = new NUMBER(0.0); |
|
1740 |
|
|
1741 |
resp[2] = null; |
|
1742 |
resp[3] = _ind; |
|
1743 |
resp[4] = _ord; |
|
1744 |
|
|
1745 |
return resp; |
|
1746 |
} |
|
1747 |
|
|
1748 |
public static String printArray(NUMBER[] array) { |
|
1687 | 1749 |
String resp = "[ "; |
1688 | 1750 |
|
1689 | 1751 |
for (int i = 0; i < array.length; i++) { |
... | ... | |
1876 | 1938 |
/** |
1877 | 1939 |
* Utility method to deal with oracle coordinate arrays. |
1878 | 1940 |
*/ |
1879 |
public static ARRAY getDevelopedOrdsArray(ARRAY ords) {
|
|
1880 |
ARRAY _resp = null;
|
|
1941 |
public static ARRAY getDevelopedOrdsArray(ARRAY ords, int dim) {
|
|
1942 |
ARRAY _resp = null;
|
|
1881 | 1943 |
|
1882 |
try { |
|
1883 |
Datum[] resp = new Datum[10]; |
|
1884 |
Datum[] corners = ords.getOracleArray(); |
|
1944 |
try { |
|
1945 |
int n = 5*2; // dim = 2, ignored dim, 3d makes no sense |
|
1946 |
Datum[] resp = new Datum[n]; |
|
1947 |
Datum[] corners = ords.getOracleArray(); |
|
1885 | 1948 |
|
1886 |
// x |
|
1887 |
resp[0] = corners[0]; |
|
1888 |
resp[2] = corners[2]; |
|
1889 |
resp[4] = corners[2]; |
|
1890 |
resp[6] = corners[0]; |
|
1891 |
resp[8] = corners[0]; |
|
1949 |
for (int i=0; i<5; i++) { |
|
1950 |
resp[i*2] = ((i==2) || (i==3)) ? corners[dim] : corners[0]; |
|
1951 |
} |
|
1952 |
for (int i=0; i<5; i++) { |
|
1953 |
resp[1+i*2] = ((i==1) || (i==2)) ? corners[dim+1] : corners[1]; |
|
1954 |
} |
|
1955 |
_resp = new ARRAY(ords.getDescriptor(), ords |
|
1956 |
.getInternalConnection(), resp); |
|
1957 |
} catch (SQLException se) { |
|
1958 |
logger.error("While creating ARRAY: " + se.getMessage(), se); |
|
1959 |
} |
|
1892 | 1960 |
|
1893 |
// y |
|
1894 |
resp[1] = corners[1]; |
|
1895 |
resp[3] = corners[1]; |
|
1896 |
resp[5] = corners[3]; |
|
1897 |
resp[7] = corners[3]; |
|
1898 |
resp[9] = corners[1]; |
|
1899 |
_resp = new ARRAY(ords.getDescriptor(), |
|
1900 |
ords.getInternalConnection(), resp); |
|
1901 |
} |
|
1902 |
catch (SQLException se) { |
|
1903 |
logger.error("While creating ARRAY: " + se.getMessage(), se); |
|
1904 |
} |
|
1961 |
return _resp; |
|
1962 |
} |
|
1905 | 1963 |
|
1906 |
return _resp; |
|
1907 |
} |
|
1908 |
|
|
1909 | 1964 |
/** |
1910 | 1965 |
* utility method to convert a STRUCT into a GeneralPathX |
1911 | 1966 |
* @param aux the struct's datum array |
... | ... | |
1927 | 1982 |
infoARRAY = (ARRAY) aux[3]; |
1928 | 1983 |
ordsARRAY = (ARRAY) aux[4]; |
1929 | 1984 |
|
1930 |
if (polStructIsRectStruct(infoARRAY, ordsARRAY)) { |
|
1931 |
infoARRAY = getDevelopedInfoArray(infoARRAY); |
|
1932 |
ordsARRAY = getDevelopedOrdsArray(ordsARRAY); |
|
1933 |
} |
|
1934 |
|
|
1935 | 1985 |
dims = ((NUMBER) aux[0]).intValue() / 1000; |
1936 | 1986 |
|
1937 | 1987 |
if (dims == 0) { |
1938 | 1988 |
dims = 2; |
1939 | 1989 |
} |
1940 | 1990 |
|
1991 |
if (polStructIsRectStruct(infoARRAY, ordsARRAY)) { |
|
1992 |
infoARRAY = getDevelopedInfoArray(infoARRAY); |
|
1993 |
ordsARRAY = getDevelopedOrdsArray(ordsARRAY, dims); |
|
1994 |
dims = 2; |
|
1995 |
} |
|
1996 |
|
|
1941 | 1997 |
info_array = (Datum[]) infoARRAY.getOracleArray(); |
1942 | 1998 |
ords_array = (Datum[]) ordsARRAY.getOracleArray(); |
1943 | 1999 |
info_array_size = info_array.length / 3; |
... | ... | |
1974 | 2030 |
next_must_do_first); |
1975 | 2031 |
} |
1976 | 2032 |
} else { |
2033 |
|
|
1977 | 2034 |
// standard case, do the moveto always |
1978 | 2035 |
for (int i = 0; i < info_array_size; i++) { |
1979 | 2036 |
lineType = getLineToType(info_array, i); |
... | ... | |
1981 | 2038 |
ords_array, dims, lineType, true, true); |
1982 | 2039 |
} |
1983 | 2040 |
} |
1984 |
|
|
1985 |
// boolean do_the_moves = true; |
|
1986 | 2041 |
} |
1987 | 2042 |
catch (SQLException se) { |
1988 | 2043 |
logger.error("While creating GPX: " + se.getMessage(), se); |
... | ... | |
2359 | 2414 |
* @param otype |
2360 | 2415 |
* @return FShape type |
2361 | 2416 |
*/ |
2362 |
public static int oracleGTypeToFShapeType(int otype, boolean complex) { |
|
2417 |
public static int oracleGTypeToFShapeType(int full_otype, boolean complex) {
|
|
2363 | 2418 |
|
2364 | 2419 |
int resp = FShape.NULL; |
2420 |
int simpl_otype = full_otype % 1000; |
|
2365 | 2421 |
|
2366 | 2422 |
if (complex) { |
2367 | 2423 |
|
2368 |
switch (otype) { |
|
2369 |
case ORACLE_GTYPE_COMPLEX_VOIDED_POLYON:
|
|
2370 |
case ORACLE_GTYPE_COMPLEX_COMPOUND_POLYON: |
|
2424 |
switch (simpl_otype) {
|
|
2425 |
case ORACLE_GTYPE_COMPLEX_VOIDED_OR_NORMAL_POLYGON:
|
|
2426 |
case ORACLE_GTYPE_COMPLEX_COMPOUND_POLYGON:
|
|
2371 | 2427 |
resp = FShape.POLYGON; |
2372 | 2428 |
break; |
2373 | 2429 |
case ORACLE_GTYPE_COMPLEX_COMPOUND_LINE: |
2374 | 2430 |
resp = FShape.LINE; |
2375 | 2431 |
break; |
2432 |
default: |
|
2433 |
return oracleGTypeToFShapeType(full_otype, false); |
|
2376 | 2434 |
} |
2377 | 2435 |
|
2378 | 2436 |
} else { |
2379 | 2437 |
|
2380 | 2438 |
// =========== not complex ================= |
2381 |
switch (otype) { |
|
2439 |
switch (simpl_otype) {
|
|
2382 | 2440 |
case ORACLE_GTYPE_UNKNOWN: |
2383 | 2441 |
resp = FShape.NULL; |
2384 | 2442 |
break; |
... | ... | |
2404 | 2462 |
} |
2405 | 2463 |
// =========== not complex ================= |
2406 | 2464 |
} |
2407 |
|
|
2408 | 2465 |
if (resp == FShape.NULL) { |
2409 |
logger.error("Unknown oracle geometry type: " + otype); |
|
2466 |
logger.error("Unknown oracle geometry type: " + full_otype);
|
|
2410 | 2467 |
} |
2411 | 2468 |
return resp; |
2412 | 2469 |
} |
... | ... | |
2654 | 2711 |
return ig; |
2655 | 2712 |
} |
2656 | 2713 |
|
2714 |
public static final int COLLECTION_VALUE_NOT_COLLECTION = 0; |
|
2715 |
public static final int COLLECTION_VALUE_YES_COLLECTION = 1; |
|
2716 |
public static final int COLLECTION_VALUE_MERGE_COLLECTION_IN_POLYGON = 2; |
|
2657 | 2717 |
|
2658 |
public static boolean isActuallyACollection(Datum[] the_data) {
|
|
2718 |
public static int isCollection(Datum[] the_data) {
|
|
2659 | 2719 |
int[] info = null; |
2660 | 2720 |
|
2661 | 2721 |
try { |
2662 | 2722 |
ARRAY aux = (ARRAY) the_data[3]; |
2663 | 2723 |
|
2664 | 2724 |
if (aux == null) { |
2665 |
return false;
|
|
2725 |
return COLLECTION_VALUE_NOT_COLLECTION;
|
|
2666 | 2726 |
} |
2667 | 2727 |
|
2668 | 2728 |
info = aux.getIntArray(); |
2669 | 2729 |
} |
2670 | 2730 |
catch (SQLException se) { |
2671 | 2731 |
logger.error("While checking collection: " + se.getMessage()); |
2672 |
return false;
|
|
2732 |
return COLLECTION_VALUE_NOT_COLLECTION;
|
|
2673 | 2733 |
} |
2674 | 2734 |
|
2675 | 2735 |
if (info == null) { |
2676 |
return false; // sdo_point
|
|
2736 |
return COLLECTION_VALUE_NOT_COLLECTION; // sdo_point
|
|
2677 | 2737 |
} |
2678 | 2738 |
|
2679 | 2739 |
int size = info.length / 3; |
2680 | 2740 |
|
2681 | 2741 |
if (size == 1) { |
2682 |
return false;
|
|
2742 |
return COLLECTION_VALUE_NOT_COLLECTION;
|
|
2683 | 2743 |
} |
2684 | 2744 |
|
2685 | 2745 |
if (size == 2) { |
2686 |
return ((info[1] % 1000) != (info[4] % 1000)) && |
|
2687 |
( ! ((info[1] == 1005) && (info[4] == 2)) ); |
|
2746 |
if (((info[1] == 1003) && (info[2] == 3 || info[2] == 4)) |
|
2747 |
|| ((info[4] == 1003 || info[4] == 2003) && (info[5] == 3 || info[5] == 4))) { |
|
2748 |
return COLLECTION_VALUE_MERGE_COLLECTION_IN_POLYGON; |
|
2749 |
} else { |
|
2750 |
boolean aux = ((info[1] % 1000) != (info[4] % 1000)) |
|
2751 |
&& ( ! ((info[1] == 1005) && (info[4] == 2)) ); |
|
2752 |
if (aux) { |
|
2753 |
return COLLECTION_VALUE_YES_COLLECTION; |
|
2754 |
} else { |
|
2755 |
return COLLECTION_VALUE_NOT_COLLECTION; |
|
2756 |
} |
|
2757 |
} |
|
2688 | 2758 |
} |
2759 |
|
|
2760 |
// ======================================== check no rects whsn size > 2 |
|
2761 |
for (int i=0; i<size; i++) { // outer pol |
|
2762 |
if ((info[i*3+1] == 1003) && (info[i*3+2] == 3 || info[i*3+2] == 4)) { |
|
2763 |
return COLLECTION_VALUE_MERGE_COLLECTION_IN_POLYGON; |
|
2764 |
} |
|
2765 |
} |
|
2766 |
for (int i=1; i<size; i++) { // inner pol |
|
2767 |
if ((info[i*3+1] == 2003) && (info[i*3+2] == 3 || info[i*3+2] == 4)) { |
|
2768 |
return COLLECTION_VALUE_MERGE_COLLECTION_IN_POLYGON; |
|
2769 |
} |
|
2770 |
} |
|
2771 |
// =================================== |
|
2689 | 2772 |
|
2773 |
int _first = info[1] % 1000; |
|
2690 | 2774 |
int second = info[4] % 1000; |
2691 | 2775 |
int item = 0; |
2692 |
|
|
2776 |
|
|
2693 | 2777 |
for (int i = 2; i < size; i++) { |
2694 | 2778 |
item = info[(i * 3) + 1] % 1000; |
2695 | 2779 |
if ((item != second) && |
2696 |
( ! ((item == 5) && (second == 2)) ) |
|
2780 |
( ! ((item == 5) && (second == 2)) ) && |
|
2781 |
( ! ((item == 2) && (second == 5)) ) |
|
2697 | 2782 |
) { |
2698 |
return true;
|
|
2783 |
return COLLECTION_VALUE_YES_COLLECTION;
|
|
2699 | 2784 |
} |
2700 | 2785 |
} |
2701 | 2786 |
|
2702 |
return false;
|
|
2787 |
return COLLECTION_VALUE_NOT_COLLECTION;
|
|
2703 | 2788 |
} |
2704 | 2789 |
|
2705 | 2790 |
|
... | ... | |
2912 | 2997 |
} |
2913 | 2998 |
} |
2914 | 2999 |
else { |
2915 |
if (((NUMBER) newaux[1]).intValue() == 2003) { |
|
2916 |
aux = appendDatArrays(aux, newaux); |
|
2917 |
} else { |
|
3000 |
|
|
3001 |
resp.add(aux); |
|
3002 |
aux = getNthGroupOfThree(all_elem, i); |
|
3003 |
// no complex subelements expected |
|
3004 |
/* |
|
3005 |
if (((NUMBER) newaux[1]).intValue() == 1003 |
|
3006 |
|| ((NUMBER) newaux[1]).intValue() == 2003) { |
|
2918 | 3007 |
resp.add(aux); |
2919 | 3008 |
aux = getNthGroupOfThree(all_elem, i); |
3009 |
} else { |
|
3010 |
aux = appendDatArrays(aux, newaux); |
|
2920 | 3011 |
} |
3012 |
*/ |
|
2921 | 3013 |
} |
2922 | 3014 |
|
2923 | 3015 |
i++; |
2924 | 3016 |
} |
2925 | 3017 |
} |
2926 |
catch (SQLException se) { |
|
3018 |
catch (SQLException se) {
|
|
2927 | 3019 |
logger.error("Unexpected error: " + se.getMessage()); |
2928 | 3020 |
} |
2929 | 3021 |
|
... | ... | |
3226 | 3318 |
public static int maxSizeForFieldType(int _type) { |
3227 | 3319 |
switch (_type) { |
3228 | 3320 |
case Types.VARCHAR: |
3229 |
return OracleSpatialDriver.VARCHAR2_STANDARD_SIZE; |
|
3230 |
|
|
3231 | 3321 |
case Types.LONGVARCHAR: |
3232 |
return OracleSpatialDriver.VARCHAR2_LONG_SIZE;
|
|
3322 |
return OracleSpatialDriver.VARCHAR2_MAX_SIZE;
|
|
3233 | 3323 |
} |
3234 | 3324 |
|
3235 | 3325 |
return -1; |
3236 | 3326 |
} |
3237 | 3327 |
|
3238 | 3328 |
|
3329 |
|
|
3239 | 3330 |
public static String EXPONENTIAL_INDICES_CONDITION = null; |
3240 | 3331 |
|
3241 | 3332 |
static { |
... | ... | |
3277 | 3368 |
return ShapeFactory.createPolyline2D(gpx); |
3278 | 3369 |
} |
3279 | 3370 |
} |
3371 |
|
|
3372 |
public static IGeometry mergePolygons(FGeometryCollection gco) { |
|
3373 |
GeneralPathX gpx = new GeneralPathX(); |
|
3374 |
|
|
3375 |
IGeometry[] gg = gco.getGeometries(); |
|
3376 |
int cnt = gg.length; |
|
3377 |
IGeometry ig2d; |
|
3378 |
for (int i=0; i<cnt; i++) { |
|
3379 |
ig2d = gg[i]; |
|
3380 |
gpx.append(ig2d.getPathIterator(null), false); |
|
3381 |
} |
|
3382 |
return ShapeFactory.createPolygon2D(gpx); |
|
3383 |
} |
|
3384 |
|
|
3385 |
public static int estimateGoodFetchSize(ResultSetMetaData md) { |
|
3386 |
|
|
3387 |
int bytesum = 0; |
|
3388 |
try { |
|
3389 |
int sz = md.getColumnCount(); |
|
3390 |
int inc = 0; |
|
3391 |
for (int i=1; i<=sz; i++) { |
|
3392 |
inc = md.getColumnDisplaySize(i); |
|
3393 |
if ((inc >= 0) && (inc <= OracleSpatialDriver.VARCHAR2_MAX_SIZE)) { |
|
3394 |
bytesum = bytesum + inc; |
|
3395 |
} |
|
3396 |
} |
|
3397 |
// TODO Auto-generated method stub |
|
3398 |
} catch (SQLException se) { |
|
3399 |
logger.warn("Error while getting field sizes: " + se.getMessage()); |
|
3400 |
logger.warn("Used: row size = 5000 bytes."); |
|
3401 |
bytesum = 5000; |
|
3402 |
} |
|
3403 |
|
|
3404 |
return Math.max(10, FETCH_BLOCK_SIZE_BYTES / bytesum); |
|
3405 |
} |
|
3280 | 3406 |
|
3281 | 3407 |
|
3282 | 3408 |
|
Also available in: Unified diff