/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2012, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.coverage.postgresql.epsg; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; import java.util.List; import java.util.ResourceBundle; /** * Contain all queries, backed by a property file. * * @author Johann Sorel (Geomatys) */ public enum PGEPSGQueries { NEXT_CODE, CREATE_ALIAS, CREATE_AREA, CREATE_CHANGE, CREATE_COORDINATE_AXIS, CREATE_COORDINATE_AXIS_NAME, CREATE_COORDINATE_REFERENCE_SYSTEM, CREATE_COORDINATE_SYSTEM, CREATE_COORDINATE_OPERATION, CREATE_COORDINATE_OPERATION_METHOD, CREATE_COORDINATE_OPERATION_PARAMETER, CREATE_COORDINATE_OPERATION_PARAMETER_USAGE, CREATE_COORDINATE_OPERATION_PARAMETER_VALUE, CREATE_COORDINATE_OPERATION_PATH, CREATE_DATUM, CREATE_DEPRECATION, CREATE_ELLIPSOID, CREATE_NAMING_SYSTEM, CREATE_PRIME_MERIDIAN, CREATE_SUPERSESSION, CREATE_UNIT_OF_MEASURE, CREATE_VERSION_HISTORY, FIND_COORDINATE_REFERENCE_SYSTEM, FIND_COORDINATE_SYSTEM, FIND_DATUM, FIND_ELLIPSOID, FIND_PRIME_MERIDIAN, FIND_UNIT_OF_MEASURE, FIND_UNIT_OF_MEASURE_SELF; private final String query; private final Integer[] parameters; private PGEPSGQueries() { final String stmt = ResourceBundle.getBundle("org/geotoolkit/coverage/postgresql/epsg_queries").getString(name()); final StringBuilder sb = new StringBuilder(); int before = 0; final List<Integer> params = new ArrayList<Integer>(); for(int i=stmt.indexOf('?',before); i>=0; i=stmt.indexOf('?',before)){ final String part = stmt.substring(before, i); final int start = part.indexOf('['); final int end = part.indexOf(']'); if(start < 0 || end < 0){ throw new IllegalArgumentException("Invalid query "+name()+" : " + stmt); } final String type = part.substring(start+1, end); try { final Field f = Types.class.getField(type); params.add(f.getInt(null)); } catch (Exception ex) { throw new IllegalArgumentException("Type unknowed : "+type+", Invalid query "+name()+" : " + stmt); } sb.append(part.substring(0, start)); sb.append(part.substring(end+1)); sb.append('?'); before = i+1; } sb.append(stmt.substring(before)); this.parameters = params.toArray(new Integer[params.size()]); this.query = sb.toString(); } public String query(){ return query; } public int getNbParameters(){ return parameters.length; } /** * Create and fill prepared statement. * The original query statement may be modified if some parameters are null. * example : SELECT * FROM house WHERE user=[INTEGER]? * will be replaced by : SELECT * FROM house WHERE user IS NULL , if paramter is null. */ public PreparedStatement createStatement(final Connection cnx, Object ... params) throws SQLException { final int nb = getNbParameters(); if(nb != params.length){ throw new SQLException("Was expecting "+nb+" parameters for query but only received "+params.length); } boolean hasNullValue = false; for(Object obj : params){ hasNullValue = (obj==null); if(hasNullValue) break; } String query = this.query; //adapt query for null values if(hasNullValue){ final List<Object> noNullParams = new ArrayList<Object>(); final StringBuilder sb = new StringBuilder(); int before = 0; for(int i=query.indexOf('?',before),k=0; i>=0; i=query.indexOf('?',before),k++){ final Object param = params[k]; final String part = query.substring(before, i); nullReplace: if(param == null){ //check if we have a '=' before for(int t=part.length()-1;t>=0;t--){ final char c = part.charAt(t); if(c == '='){ sb.append(part.substring(0,t)); sb.append(" IS NULL "); break nullReplace; }else if(c != ' '){ break; } } noNullParams.add(param); sb.append(part); sb.append('?'); }else{ noNullParams.add(param); sb.append(part); sb.append('?'); } before = i+1; } //add remaining params = noNullParams.toArray(); sb.append(query.substring(before)); query = sb.toString(); } final PreparedStatement stmt = cnx.prepareStatement(query); fill(stmt, params); return stmt; } /** * Caution : if some arguments may be null consider using 'create' method to * automaticly refactor the query. */ public void fillStatement(final PreparedStatement stmt, final Object ... params) throws SQLException{ final int nb = getNbParameters(); if(nb != params.length){ throw new SQLException("Was expecting "+nb+" parameters for query but only received "+params.length); } if(nb == 0){ //nothing to fill return; } fill(stmt, params); } private void fill(final PreparedStatement stmt, final Object ... params) throws SQLException{ for(int i=0;i<params.length;i++){ final Object param = params[i]; if(param != null){ stmt.setObject(i+1, params[i], parameters[i]); }else{ stmt.setNull(i+1, parameters[i]); } } } }