[Gvsig_desarrolladores] Campos Numericos largos en shapes

Daniel pumukovic en hotmail.com
Vie Dic 14 09:37:27 CET 2012


Hola, a raiz de tratar de manejar en gvSIG un shape concretamente de
Cartociudad me he dado cuenta de un bug de gvSIG. Concretamente cuando
viene un tipo de dato numérico sin decimales y no es representable como
entero, gvsig le pone un 0 a todos los atributos de ese campo. 
Básicamente el problema está en que gvSIG en esos casos trata de
utilizar el tipo int, no siendo siempre una solución correcta pues para
números enteros largos quedan fuera del rango de esta representación. 

Lo he solucionado verificando la longitud del campo y a partir de un
tamaño diferenciar si es int o double (traté de utilizar long y vi que
seguía pasando además de ver que en otros campos largos pese a no tener
decimales venian definidos como doubles)


adjunto como han quedado los 2 metodos modificados de la clase
 com.iver.cit.gvsig.fmap.drivers.dbf.DBFDriver

Un saludo



------------ próxima parte ------------
Primer método modificado:
    

/**
     * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldValue(long,
     *      int)
     */
    public Value getFieldValue(long rowIndex, int fieldId)
        throws ReadDriverException {
        // Field Type (C  or M)
        char cfieldType = fieldTypes[fieldId];
        int fieldType = getFieldType(fieldId);

    	String strValue;


    	if (cfieldType == 'D') {
            String date;
			try {
				date = dbf.getStringFieldValue((int) rowIndex, fieldId).trim();
			} catch (UnsupportedEncodingException e1) {
				throw new ReadDriverException(getName(),e1);
			}
            // System.out.println(rowIndex + " data=" + date);
            if (date.length()<8) {
                return null;
            }
            String year = date.substring(0, 4);
            String month = date.substring(4, 6);
            String day = date.substring(6, 8);
            DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, ukLocale);
            /* Calendar c = Calendar.getInstance();
            c.clear();
            c.set(Integer.parseInt(year), Integer.parseInt(month),
                Integer.parseInt(day));
            c.set(Calendar.MILLISECOND, 0); */
            String strAux = month + "/" + day + "/" + year;
            Date dat;
            try {
                dat = df.parse(strAux);
            } catch (ParseException e) {
                throw new ReadDriverException(getName(),e);
            }

            // System.out.println("numReg = " + rowIndex + " date:" + dat.getTime());

            return ValueFactory.createValue(dat);
        } else {

        	try {
        		strValue = dbf.getStringFieldValue((int) rowIndex, fieldId);
    		} catch (UnsupportedEncodingException e1) {
    			throw new BadFieldDriverException(getName(),e1);
    		}
   			strValue = strValue.trim();
   			if (fieldType == Types.BOOLEAN){
   				strValue = strValue.toLowerCase();
 				strValue = Boolean.toString(strValue.equals("t") || strValue.equals("y"));
   			}

    		try {
				return ValueFactory.createValueByType(strValue, fieldType);
			} catch (Exception e) {
				if (fieldType == Types.INTEGER ||
						fieldType == Types.BIGINT ||
						fieldType == Types.FLOAT ||
						fieldType == Types.DECIMAL ||
						fieldType == Types.DOUBLE){
					//Habria que quejarse???
						/*PARCHE AUTOR: Daniel Lopez Sanchez
						 * se ha detectado que para numeros sin decimales que deberian ser long se trata de resolver como int y peta y mete un cero
						 * asi que aqui tratamos de recuperar ese numero como un long antes de poner el 0
						 */
					try{
							 return ValueFactory.createValue(Long.parseLong(strValue));
						}catch(Exception e2){
							//Habria que quejarse???
							return ValueFactory.createValue(0);
						}
						
						/*FIN PARCHE*/
//						return ValueFactory.createValueByType("0", fieldType);
					
				}else{
					// OJO: Habria que revisar el resto de tipos
					// De momento lanzamos la excepcion
					throw new BadFieldDriverException(getName(),null,String.valueOf(fieldType));
				}
			}


        }
    }


Segundo método modificado:

 /**
     * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#getFieldType(int)
     */
    public int getFieldType(int i) throws ReadDriverException {
        char fieldType = fieldTypes[i];

        if (fieldType == 'L') {
            return Types.BOOLEAN;
        } else if ((fieldType == 'F') || (fieldType == 'N')) {
        	if (dbf.getFieldDecimalLength(i)>0)
        		return Types.DOUBLE;
        	else
        		if(dbf.getFieldLength(i)>9)
        			return Types.DOUBLE;
        		else
        			return Types.INTEGER;
        } else if (fieldType == 'C') {
            return Types.VARCHAR;
        } else if (fieldType == 'D') {
            return Types.DATE;
        } else {
            throw new BadFieldDriverException(getName(),null,String.valueOf(fieldType));
        }
    }



Más información sobre la lista de distribución gvSIG_desarrolladores