All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.h2gis.utilities.TableLocation Maven / Gradle / Ivy

Go to download

Collection of methods to fetch spatial metadata in SFS database like PostGIS or H2Spatial. Theses functions can be commonly used either in PostGIS or in H2. Spatial utilities publish also a DataSourceFactory wrapper that provide JDBC Wrapper for spatial functionality.

There is a newer version: 1.2.4
Show newest version
/**
 * H2GIS is a library that brings spatial support to the H2 Database Engine
 * .
 *
 * H2GIS is distributed under GPL 3 license. It is produced by CNRS
 * .
 *
 * H2GIS is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * H2GIS 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * H2GIS. If not, see .
 *
 * For more information, please consult: 
 * or contact directly: info_at_h2gis.org
 */
package org.h2gis.utilities;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.regex.Pattern;

/**
 * Just a class used to split Catalog Schema and Table. Theses components are a unique table identifier.
 * @author Nicolas Fortin
 */
public class TableLocation {
    private String catalog,schema,table;
    /** Recognized by H2 and Postgres */
    private static final String QUOTE_CHAR = "\"";
    private static final Pattern POSTGRE_SPECIAL_NAME_PATTERN = Pattern.compile("^[a-z]{1,1}[a-z0-9_]*$");
    private static final Pattern H2_SPECIAL_NAME_PATTERN = Pattern.compile("^[A-Z]{1,1}[A-Z0-9_]*$");
    private String defaultSchema = "PUBLIC";

    /**
     * @param rs result set obtained through {@link java.sql.DatabaseMetaData#getTables(String, String, String, String[])}
     * @throws SQLException
     */
    public TableLocation(ResultSet rs) throws SQLException {
        this(rs.getString("TABLE_CAT"),rs.getString("TABLE_SCHEM"),rs.getString("TABLE_NAME"));
    }

    /**
     *
     * @param catalog Catalog name without quotes
     * @param schema Schema name without quotes
     * @param table Table name without quotes
     */
    public TableLocation(String catalog, String schema, String table) {
        if(table == null) {
            throw new IllegalArgumentException("Cannot construct table location with null table");
        }
        this.catalog = catalog == null ? "" : catalog;
        this.schema = schema  == null || schema.isEmpty() ? "" : schema;
        this.table = table;
    }

    /**
     * @param schema Schema name without quotes
     * @param table Table name without quotes
     */
    public TableLocation(String schema, String table) {
        this("",schema,table);
    }

    /**
     * @param table Table name without quotes
     */
    public TableLocation(String table) {
        this("", table);
    }

    /**
     * Always Quote string for both H2 and Postgre compatibility
     * @param identifier Catalog,Schema,Table or Field name
     * @return Quoted Identifier
     */
    public static String quoteIdentifier(String identifier) {
        return QUOTE_CHAR+identifier.replace("\"","\"\"")+QUOTE_CHAR;
    }


    /**
     * Quote identifier only if necessary. Require database knowledge.
     * @param identifier Catalog,Schema,Table or Field name
     * @param isH2DataBase True if the quote is for H2, false if for POSTGRE
     * @return Quoted Identifier
     */
    public static String quoteIdentifier(String identifier, boolean isH2DataBase) {
        if((isH2DataBase && (Constants.H2_RESERVED_WORDS.contains(identifier.toUpperCase())
                        || !H2_SPECIAL_NAME_PATTERN.matcher(identifier).find())) ||
                (!isH2DataBase && (Constants.POSTGIS_RESERVED_WORDS.contains(identifier.toUpperCase())
                        || !POSTGRE_SPECIAL_NAME_PATTERN.matcher(identifier).find()))) {
            return quoteIdentifier(identifier);
        } else {
            return identifier;
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        if(!catalog.isEmpty()) {
            sb.append(quoteIdentifier(catalog));
            sb.append(".");
        }
        if(!schema.isEmpty()) {
            sb.append(quoteIdentifier(schema));
            sb.append(".");
        }
        sb.append(quoteIdentifier(table));
        return sb.toString();
    }

    /**
     * String representation of Table location, for insertion in SQL statement.
     * This function try to do not quote unnecessary components; require database type.
     * @param isH2 True if H2, false if
     * @return String representation of Table location
     */
    public String toString(boolean isH2) {
        StringBuilder sb = new StringBuilder();
        if(!catalog.isEmpty()) {
            sb.append(quoteIdentifier(catalog, isH2));
            sb.append(".");
        }
        if(!schema.isEmpty()) {
            sb.append(quoteIdentifier(schema, isH2));
            sb.append(".");
        }
        sb.append(quoteIdentifier(table, isH2));
        return sb.toString();
    }

    /**
     * @return Table catalog name (database)
     */
    public String getCatalog() {
        return catalog;
    }


    /**
     * @param defaultValue Return this value if this attribute is not defined.
     * @return Table catalog name (database)
     */
    public String getCatalog(String defaultValue) {
        return catalog.isEmpty() ? defaultValue : catalog;
    }

    /**
     * Convert catalog.schema.table, schema.table or table into a TableLocation
     * instance. Non-specified schema or catalogs are converted to the empty
     * string.
     *
     * @param concatenatedTableLocation Table location [[Catalog.]Schema.]Table
     * @return Java beans for table location
     */
    public static TableLocation parse(String concatenatedTableLocation) {
        return parse(concatenatedTableLocation, null);
    }

    /**
     * Convert catalog.schema.table, schema.table or table into a TableLocation
     * instance. Non-specified schema or catalogs are converted to the empty
     * string.
     *
     * @param concatenatedTableLocation Table location [[Catalog.]Schema.]Table
     * @param isH2Database              True if H2, False if PostGreSQL, null if unknown
     * @return Java beans for table location
     */
    public static TableLocation parse(String concatenatedTableLocation, Boolean isH2Database) {
        List parts = new LinkedList();
        String catalog,schema,table;
        catalog = table = schema = "";
        StringTokenizer st = new StringTokenizer(concatenatedTableLocation, ".`\"", true);
        boolean openQuote = false;
        StringBuilder sb = new StringBuilder();
        while(st.hasMoreTokens()) {
            String token = st.nextToken();
            if(token.equals("`") || token.equals("\"")) {
                openQuote = !openQuote;
            } else if(token.equals(".")) {
                if(openQuote) {
                    // Still in part
                    sb.append(token);
                } else {
                    // end of part
                    parts.add(sb.toString());
                    sb = new StringBuilder();
                }
            } else {
                if(!openQuote && isH2Database != null) {
                    token = capsIdentifier(token, isH2Database);
                }
                sb.append(token);
            }
        }
        if(sb.length() != 0) {
            parts.add(sb.toString());
        }
        String[] values = parts.toArray(new String[parts.size()]);
        switch (values.length) {
            case 1:
                table = values[0].trim();
                break;
            case 2:
                schema = values[0].trim();
                table = values[1].trim();
                break;
            case 3:
                catalog = values[0].trim();
                schema = values[1].trim();
                table = values[2].trim();
        }
        return new TableLocation(catalog,schema,table);
    }

    /**
     * Change case of parameters to make it more user-friendly.
     *
     * @param identifier   Table, Catalog, Schema, or column name
     * @param isH2Database True if H2, False if PostGreSQL, null if unknown
     * @return Upper or lower case version of identifier
     */
    public static String capsIdentifier(String identifier, Boolean isH2Database) {
        if(isH2Database != null) {
            if(isH2Database) {
                return identifier.toUpperCase();
            } else {
                return identifier.toLowerCase();
            }
        } else {
            return identifier;
        }
    }

    /**
     * @return Table schema name
     */
    public String getSchema() {
        return schema;
    }

    /**
     * @param defaultValue Return this value if this attribute is not defined.
     * @return Table schema name
     */
    public String getSchema(String defaultValue) {
        return schema.isEmpty() ? defaultValue : schema;
    }
    /**
     * @return Table name
     */
    public String getTable() {
        return table;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof TableLocation)) return false;

        TableLocation that = (TableLocation) o;

        return  (catalog.equals(that.catalog) || catalog.isEmpty() || that.catalog.isEmpty()) &&
                (schema.equals(that.schema) || (schema.equals(defaultSchema) && that.schema.isEmpty()) ||
                (that.schema.equals(defaultSchema) && schema.isEmpty())) &&
                table.equals(that.table);
    }

    @Override
    public int hashCode() {
        int result = catalog.hashCode();
        result = 31 * result + schema.hashCode();
        result = 31 * result + table.hashCode();
        return result;
    }

    /**
     * @param defaultSchema Default connection schema, used for table location equality test.
     */
    public void setDefaultSchema(String defaultSchema) {
        this.defaultSchema = defaultSchema;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy