WQMTools.java [src/java/wqm/utils] Revision:   Date:
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package wqm.utils;


import java.util.ArrayList;


/**
 *
 * @author Shaun Case
 */
public class WQMTools {

//    // Only access these from a 'synchronized' member function...
//    private static ConcurrentHashMap<String, DataSource> dataSources = new ConcurrentHashMap<>();
//    private static ConcurrentHashMap<String, String> connectionStrings = new ConcurrentHashMap<>();
//
//    public static String getR2GISFileURL(String path, String name) throws MalformedURLException {
//	return ((("http://" + wqm.utils.WQMTools.getDatabaseHostname("r2gis") + "/r2/" + path + "/" + name + ".xml")).replace(" ", "%20")).replace("\\", "/");
//    }
//
//    //If at some point it becomes a performance issue, this method could be made to not be 'synchronized', as this syncs on the actual
//    //  WQMTools as a whole.  A speedier implementation would be to synchronize() on the HashMaps, and use synchronized blocks of code.
//    //  this could potentially allow for other threads looking for already built connections to continue with their work without having
//    //  to wait on the threads looking for connections that have not yet been built and pooled, which is what happens now when the function
//    //  in its entirety is synchronized.  If multiple hits per second are happening to the WQM service, then this might need to be done, as
//    //  in testing the initial db connections prove to take around 1 sec, and once pooled take only milliseconds to return.
//    public static synchronized Connection getConnection(String className, SessionLogger logger) throws csip.ServiceException {
//	Connection ret_val = null;
//	boolean debugging = Boolean.parseBoolean(Config.getString("debugging", "false"));
//
//	if (null != className) {
//	    //Don't need to synchronize() around these calls because they are already in a synchronized member
//	    if (!connectionStrings.containsKey(className)) {
//		connectionStrings.put(className, Config.getString((debugging ? className.toLowerCase() + ".debug.db" : className.toLowerCase() + ".db")));
//
//	    }
//
//	    if (connectionStrings.get(className) == null || connectionStrings.get(className).isEmpty()) {
//		if (logger != null) {
//		    logger.log(Level.SEVERE, "Connection string not provided.  Please configure wqm.db configuration parameter.");
//		}
//		throw new csip.ServiceException("Unable to connect to WQM database.  Please check the " + (debugging ? className.toLowerCase() + ".debug.db" : className.toLowerCase() + ".db") + " configuration parameter");
//	    }
//
//	    try {
//		if (!dataSources.containsKey(className)) {
//		    createDataSource(className, Config.getString(className + ".db.driver", "org.postgresql.Driver"), logger);
//		}
//
//		ret_val = dataSources.get(className).getConnection();
//	    } catch (SQLException ex) {
//		if (logger != null) {
//		    logger.log(Level.SEVERE, null, ex);
//		}
//		throw new csip.ServiceException("Failed to connect to WQM database.  Please check the " + className + " configuration parameter: " + ex.getMessage());
//	    }
//	}
//	return ret_val;
//    }
//
//    private static String getDatabaseHostname(String className) throws MalformedURLException {
//	String ret_val;
//	boolean debugging = Boolean.parseBoolean(Config.getString("debugging", "false"));
//
//	ret_val = new URL(Config.getString((debugging ? className + ".debug.db" : className + ".db")).replace("jdbc:postgresql", "http")).getHost();
//
//	return ret_val;
//    }
//
//    //Doesn't 'need' to be synchronized because it should only be called by getConnection() which is synchronized, 
//    //  but just in case someone tries calling it elsewhere within this class at a later date...leave it synchronized.
//    private static synchronized void createDataSource(String className, String DriverClassName, SessionLogger logger) throws SQLException {
//	PoolProperties p = new PoolProperties();
//	p.setUrl(connectionStrings.get(className));
//	//p.setDefaultReadOnly( true );
//	p.setDriverClassName(DriverClassName);
//	p.setJmxEnabled(false);
//	p.setTestOnBorrow(true);
//	p.setValidationQuery("SELECT 1");
//	p.setTestOnReturn(false);
//	p.setValidationInterval(30000);
//	p.setTimeBetweenEvictionRunsMillis(30000);
//	p.setMaxWait(10000);
//	p.setRemoveAbandonedTimeout(30);  //Experimentally find an optimal value for this...
//	p.setRemoveAbandoned(true);
//	p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
//		+ "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;"
//		+ "org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer");
//
//	dataSources.put(className, new org.apache.tomcat.jdbc.pool.DataSource(p));
//	if (logger != null) {
//	    logger.log(Level.INFO, "\nCreated datasource {0}", dataSources.get(className).toString());
//	}
//    }

    /*
     public static void shutdownDataSource() {
     if (datasourceR2GIS != null && datasourceR2GIS instanceof DataSourceProxy) {
     DataSourceProxy proxy = (DataSourceProxy) datasourceR2GIS;
     proxy.close(true);
     datasourceR2GIS = null;
     }
        
     if (datasourceSSURGO != null && datasourceSSURGO instanceof DataSourceProxy) {
     DataSourceProxy proxy = (DataSourceProxy) datasourceSSURGO;
     proxy.close(true);
     datasourceSSURGO = null;
     }
        
     if (datasourceWQM != null && datasourceWQM instanceof DataSourceProxy) {
     DataSourceProxy proxy = (DataSourceProxy) datasourceWQM;
     proxy.close(true);
     datasourceWQM = null;
     }        
     } 
     */
    public static class PolygonLatLon {

	private ArrayList<WQMTools.PolygonLatLon.PointLatLon> points;
	private Boolean bValid;

	public PolygonLatLon() {
	    this.bValid = true;
	    this.points = new ArrayList<>();
	}

	public PolygonLatLon(ArrayList<WQMTools.PolygonLatLon.PointLatLon> tPoints) {
	    if (null != tPoints) {
		this.bValid = true;
		this.points = new ArrayList<>(tPoints);
		for (WQMTools.PolygonLatLon.PointLatLon tPoint : tPoints) {
		    if (!tPoint.isValid()) {
			this.bValid = false;
			break;
		    }
		}
	    }
	}

	public void add(WQMTools.PolygonLatLon.PointLatLon tPoint) {
	    this.points.add(tPoint);
	    if (!tPoint.isValid()) {
		this.bValid = false;
	    }
	}

	public void add(Double Lat, Double Lon) {
	    WQMTools.PolygonLatLon.PointLatLon tPoint = new WQMTools.PolygonLatLon.PointLatLon(Lat, Lon);
	    this.points.add(tPoint);
	    if (!tPoint.isValid()) {
		this.bValid = false;
	    }
	}

	public String toWKT() {
	    String ret_val = "";
	    int currentPoint = 0;
	    StringBuilder buff = new StringBuilder();

	    if (this.bValid) {
		buff.append("'POLYGON((");
		for (WQMTools.PolygonLatLon.PointLatLon tPoint : this.points) {
		    if (currentPoint > 0) {
			buff.append(", ");
		    }
		    //  Remember Lon is X and Lat is Y...
		    buff.append(tPoint.getLon().toString());
		    buff.append(" ");
		    buff.append(tPoint.getLat().toString());
		    //ret_val += tPoint.getLon().toString() + " " + tPoint.getLat().toString();
		    currentPoint++;
		}

		buff.append("))'");
		ret_val = buff.toString();
	    }

	    return ret_val;
	}

	public Boolean isValid() {
	    return this.bValid;
	}

	public static class PointLatLon {

	    private Double Lat;
	    private Double Lon;
	    private Boolean bValid;

	    public PointLatLon(Double Lat, Double Lon) {
		this.Lat = Lat;
		this.Lon = Lon;
		this.bValid = true;

		if (Math.abs(Lon) > 180) {
		    this.bValid = false;
		}

		if (Math.abs(Lat) > 90) {
		    this.bValid = false;
		}
	    }

	    public Boolean isValid() {
		return this.bValid;
	    }

	    public Double getLat() {
		return this.Lat;
	    }

	    public Double getLon() {
		return this.Lon;
	    }

	    public void setLon(Double Lon) {
		this.Lon = Lon;
		if (Math.abs(Lon) > 180) {
		    this.bValid = false;
		}
	    }

	    public void setLat(Double Lat) {
		this.Lat = Lat;
		if (Math.abs(Lat) > 90) {
		    this.bValid = false;
		}
	    }
	}
    }
}