Thursday, March 29, 2012

Do you want to migrate layers from Geoserver 1.7 to 2.1? ... here is procedure for styles ...

keywords: java, geoserver, SLD migration, File, FileWriter, FilenameFilter, HSQL

...maybe some of you still have Geoserver 1.7 running in production environment and you plan to migrate to version 2.1. Recently I had a similar task … if you have a lot of layers and lot of styles it can be a pretty boring job :-)

To help a little bit I have wrote java class that can help you with style migration. It was a easy task. Maybe I’ll also post application for layer migration … (if I develop one) …. There is a source code for SLD migration at the end of post. Included MD5 method is not necessary but you have to provide unique ID for style. Besides, I don’t take credit for md5 because I found it on internet (don’t remember link …sorry to author).... it seems that works good. For java novice this can be reference how to list folder using filter and how to write to file. Hope that this helps someone ....

Be careful if you already have some features published on Geoserver 2.1. Do not run application directly in styles folder because you can overwrite already used sld files, the value in xml file will be changed and the layer that uses that style will be invalid (Geoserver 2.1. for every sld file have xml file with the same name). Use application in the separate folder and then copy all files (sld and matching xml) into the geoservers style folder. … hmmm you will have to restart geoserver... I’m not sure (but it is easy to check) to avoid any problem that can happen first stop geoserver than copy files and start it again.

There is hsql database that is created when you start geoserver. Some values are stored in it and it can produce problem when you change something directly in folders (without geoserver). If you run into some problems you can delete database in the container temp folder ( Djava.io.tmpdir\Geotools\Databases\HSQL\v7.9.0). When you delete v7.9.0 folder after restart the new folder will be created. I use: Tomcat 7.0.26; Geoserver 2.1.3 rev.16668; GeoTools Version 2.7.4 rev.38443. You may have some other folder but principle is the same … if Geoserver hangs, delete hsql and restart Tomcat :-)

Anyway if you have 100 SLD files it is much easier to stop and start geoserver than to work with one style at the time ... 

... enjoy! 


package my.util.migration.sld;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;

public class XMLGenerator {
    
    private  String getStyleTemplate(){
        String xmlTemplate ="";
        xmlTemplate = xmlTemplate + "<style>\n";
        xmlTemplate = xmlTemplate + "  <id>:style_id:</id>\n";
        xmlTemplate = xmlTemplate + "  <name>:style_name:</name>\n";
        xmlTemplate = xmlTemplate + "  <sldVersion>\n";
        xmlTemplate = xmlTemplate + "    <version>1.0.0</version>\n";
        xmlTemplate = xmlTemplate + "  </sldVersion>\n";
        xmlTemplate = xmlTemplate + "  <filename>:style_filename:</filename>\n";
        xmlTemplate = xmlTemplate + "</style>";
        
        return xmlTemplate;
    }
    
    public void createXML(String sld_file_name, String xmlTemplate, String dest_path){
        String xmName = sld_file_name.replace(".sld",".xml");
        
        xmlTemplate = xmlTemplate.replace(":style_id:", MD5(sld_file_name));
        xmlTemplate = xmlTemplate.replace(":style_name:", sld_file_name.replace(".sld",""));
        xmlTemplate = xmlTemplate.replace(":style_filename:", sld_file_name );
        
        
        FileWriter fstream;
        try {
            
            File f = new File(dest_path);
            fstream = new FileWriter(f.getAbsolutePath() + File.separator + xmName);

            BufferedWriter out = new BufferedWriter(fstream);
            out.write(xmlTemplate);
            //Close the output stream
            out.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }        
    }
    
    public String MD5(String md5) {
           try {
                java.security.MessageDigest md = 
                  java.security.MessageDigest.getInstance("MD5");
                byte[] array = md.digest(md5.getBytes());
                StringBuffer sb = new StringBuffer();
                for (int i = 0; i < array.length; ++i) {
                  sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
               }
                return sb.toString();
            } catch (java.security.NoSuchAlgorithmException e) {
            }
            return null;
        }
    
    public void prepareForGS21(String old_path){
        
        XMLGenerator xmlg = new XMLGenerator();
        File f = new File(old_path);
        
        FilenameFilter filter = new FilenameFilter() {
            public boolean accept(File dir, String name) {
                name=name.toLowerCase();
                return name.endsWith(".sld");
            }
        };
        
        String [] files ;
        files = f.list(filter);
        
        if(files.length !=0){
            for(int i=0; i< files.length; i++){
                //System.out.println(files[i]);
                xmlg.createXML(files[i],xmlg.getStyleTemplate(), old_path);
            }
        }
    }

    
    public static void main(String[] args) {
        XMLGenerator xmlg = new XMLGenerator();
        String path;
        
        if(args.length > 0){
            path = args[0];
        }else{
            System.out.println("XMLGenerator <path>");
            System.out.println("path:\tFolder with the old SLD files\n\tIt will be used as a destination folder for xml files used by Geoserver 2.1");
            System.out.println("\tFor testing u can use /tmp/test or c:\\tmp\\test folder. No need to enter value for path.");
            path = File.separator + "tmp" + File.separator + "test"; 
        }
        xmlg.prepareForGS21(path);   
    }
}

Tuesday, March 27, 2012

Inspect data and prepare catalog with PL/SQL … (Oracle case)

keywords: pl/sql, cursor, oracle, geoserver, sld

Sometimes happens that you have plenty of tables that you have to publish as layers on Geoserver and you have to produce SLD... it could be some other GIS tool or engine ...anyway, without some specification or catalog you will get a lot of overhead work.

Easy way to produce catalog that contains some basic elements such as geometry type and attribute values needed for symbology can be done using PL/SQL. In this particular case values of attribute VRSTA are important for symbology... of course, as it is always the case, the geometry type was also needed (point, line, polygon).

Using presented anonymous block you will get all distinct values in the field VRSTA (category) and geometry used for visualisation (GTYPE) as well as geometry field name for every table in the PPSV shema. To cover some different case that may happen you can modify cursors in the declare part of procedure and variables related to cursor.

This procedure is also good example how to create cursor that has table name as parameter (c_vrsta).

To make it more clear...
PPSV: database user/schema with tables
VRSTA(eng. category): column name in tables that is used for categorisation (by convention it is named VRSTA)


declare
 cursor c_tablice is select distinct(table_name) t_name from  all_tab_cols where owner = 'PPSV' and column_name = 'VRSTA' and table_name not like '%$%';
 cursor c_gtables is select table_name t_name, column_name c_name from  all_tab_cols where owner = 'PPSV' and  table_name not like '%$%' and data_type = 'SDO_GEOMETRY';

 type vrsta_type is ref cursor;
 c_vrsta vrsta_type;
 vrsta varchar2(1000);
 v_sql varchar2(1000);
begin
for  r_tablice in c_tablice
loop
  dbms_output.put_line('> TABLE: '||r_tablice.t_name);
      open c_vrsta for 'select distinct(VRSTA) d_vrsta from '||r_tablice.t_name;
          loop
       fetch c_vrsta into vrsta ;
             exit when c_vrsta%NOTFOUND;
             dbms_output.put_line('  VRSTA: '|| vrsta);
          end loop;
      dbms_output.put_line('');
      close  c_vrsta;
end loop;    

for  r_tablice in c_gtables
loop
  dbms_output.put_line('> TABLE: '||r_tablice.t_name || '   GEOMETRY FIELD: ' || r_tablice.c_name);
  v_sql := 'select distinct(tb.' || r_tablice.c_name || '.sdo_gtype) g_vrsta from '|| r_tablice.t_name || '  tb';
  --dbms_output.put_line(v_sql);
      open c_vrsta for v_sql;
          loop
       fetch c_vrsta into vrsta ;
             exit when c_vrsta%NOTFOUND;
             dbms_output.put_line('  GTYPE: '|| vrsta);
          end loop;
      dbms_output.put_line('');
      close  c_vrsta;
end loop;
end;
/

Wednesday, March 14, 2012

Jump into the 3D GIS world: Easy WorldWind Starter for Eclipse


  • download WorldWind SDK http://worldwind.arc.nasa.gov/java/
  • extract worldwind-1.2.0.zip
  • start Eclipse
  • create project named My3DStarter
  • copy content of the worldwind-1.2.0.zip to project folder (my3D)
  • check for reference libraries. There should be at least: jogl.jar, gluegen-rt.jar, plugin.jar, gdal.jar
...and that's all. Now play with plenty of examples from the package gov.nasa.worldwindx.examples

You may consider to start with HelloWorldWind and ApplicationTemplate.

To start your own application it is good idea to use ApplicationTemplate as a starter:
  • create new Java Class (test.ww3d.MyApp) and copy source code from ApplicationTemplate Class
  • rename package name and class name as it was originally named
  • change the main method -> MyApp("Up and running :-)", AppFrame.class);
  • add import -> import gov.nasa.worldwindx.examples.*; (or if you want you can add one line for each class that is actually needed)
  • run it!