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

org.eobjects.metamodel.AbstractDataContext Maven / Gradle / Ivy

There is a newer version: 5.3.6
Show newest version
/**
 * eobjects.org MetaModel
 * Copyright (C) 2010 eobjects.org
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program 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.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package org.eobjects.metamodel;

import java.util.Arrays;
import java.util.Map;
import java.util.TreeMap;

import org.eobjects.metamodel.data.DataSet;
import org.eobjects.metamodel.query.CompiledQuery;
import org.eobjects.metamodel.query.DefaultCompiledQuery;
import org.eobjects.metamodel.query.Query;
import org.eobjects.metamodel.query.builder.InitFromBuilder;
import org.eobjects.metamodel.query.builder.InitFromBuilderImpl;
import org.eobjects.metamodel.query.parser.QueryParser;
import org.eobjects.metamodel.schema.Column;
import org.eobjects.metamodel.schema.Schema;
import org.eobjects.metamodel.schema.Table;

/**
 * Abstract implementation of the DataContext interface. Provides convenient
 * implementations of all trivial and datastore-independent methods.
 * 
 * @author Kasper Sørensen
 */
public abstract class AbstractDataContext implements DataContext {

    private final Map _schemaCache = new TreeMap(SchemaNameComparator.getInstance());
    private String[] _schemaNameCache;

    /**
     * {@inheritDoc}
     */
    @Override
    public final DataContext refreshSchemas() {
        _schemaCache.clear();
        _schemaNameCache = null;
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final Schema[] getSchemas() throws MetaModelException {
        String[] schemaNames = getSchemaNames();
        for (int i = 0; i < schemaNames.length; i++) {
            String name = schemaNames[i];
            if (!_schemaCache.containsKey(name)) {
                Schema schema = getSchemaByName(name);
                _schemaCache.put(name, schema);
            }
        }
        Schema[] result = _schemaCache.values().toArray(new Schema[0]);
        return result;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final String[] getSchemaNames() throws MetaModelException {
        if (_schemaNameCache == null) {
            _schemaNameCache = getSchemaNamesInternal();
        }
        return Arrays.copyOf(_schemaNameCache, _schemaNameCache.length);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final Schema getDefaultSchema() throws MetaModelException {
        Schema result = null;
        String defaultSchemaName = getDefaultSchemaName();
        if (defaultSchemaName != null) {
            result = getSchemaByName(defaultSchemaName);
        }
        if (result == null) {
            Schema[] schemas = getSchemas();
            if (schemas.length == 1) {
                result = schemas[0];
            } else {
                int highestTableCount = -1;
                for (int i = 0; i < schemas.length; i++) {
                    Schema schema = schemas[i];
                    String name = schema.getName().toLowerCase();
                    boolean isInformationSchema = name.startsWith("information") && name.endsWith("schema");
                    if (!isInformationSchema && schema.getTableCount() > highestTableCount) {
                        highestTableCount = schema.getTableCount();
                        result = schema;
                    }
                }
            }
        }
        return result;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final InitFromBuilder query() {
        return new InitFromBuilderImpl(this);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Query parseQuery(final String queryString) throws MetaModelException {
        final QueryParser parser = new QueryParser(this, queryString);
        final Query query = parser.parse();
        return query;
    }

    @Override
    public CompiledQuery compileQuery(final Query query) throws MetaModelException {
        return new DefaultCompiledQuery(query);
    }

    @Override
    public DataSet executeQuery(CompiledQuery compiledQuery, Object... values) {
        assert compiledQuery instanceof DefaultCompiledQuery;

        final DefaultCompiledQuery defaultCompiledQuery = (DefaultCompiledQuery) compiledQuery;
        final Query query = defaultCompiledQuery.cloneWithParameterValues(values);

        return executeQuery(query);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final DataSet executeQuery(final String queryString) throws MetaModelException {
        final Query query = parseQuery(queryString);
        final DataSet dataSet = executeQuery(query);
        return dataSet;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final Schema getSchemaByName(String name) throws MetaModelException {
        Schema schema = _schemaCache.get(name);
        if (schema == null) {
            if (name == null) {
                schema = getSchemaByNameInternal(null);
            } else {
                String[] schemaNames = getSchemaNames();
                for (String schemaName : schemaNames) {
                    if (name.equalsIgnoreCase(schemaName)) {
                        schema = getSchemaByNameInternal(name);
                        break;
                    }
                }
                if (schema == null) {
                    for (String schemaName : schemaNames) {
                        if (name.equalsIgnoreCase(schemaName)) {
                            schema = getSchemaByNameInternal(schemaName);
                            break;
                        }
                    }
                }
            }
            if (schema != null) {
                _schemaCache.put(schema.getName(), schema);
            }
        }
        return schema;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final Column getColumnByQualifiedLabel(final String columnName) {
        if (columnName == null) {
            return null;
        }
        Schema schema = null;
        final String[] schemaNames = getSchemaNames();
        for (final String schemaName : schemaNames) {
            if (schemaName == null) {
                // search without schema name (some databases have only a single
                // schema with no name)
                schema = getSchemaByName(null);
                if (schema != null) {
                    Column column = getColumn(schema, columnName);
                    if (column != null) {
                        return column;
                    }
                }
            } else {
                // Search case-sensitive
                Column col = searchColumn(schemaName, columnName, columnName);
                if (col != null) {
                    return col;
                }
            }
        }

        final String columnNameInLowerCase = columnName.toLowerCase();
        for (final String schemaName : schemaNames) {
            if (schemaName != null) {
                // search case-insensitive
                String schameNameInLowerCase = schemaName.toLowerCase();
                Column col = searchColumn(schameNameInLowerCase, columnName, columnNameInLowerCase);
                if (col != null) {
                    return col;
                }
            }
        }

        schema = getDefaultSchema();
        if (schema != null) {
            Column column = getColumn(schema, columnName);
            if (column != null) {
                return column;
            }
        }

        return null;
    }

    /**
     * Searches for a particular column within a schema
     * 
     * @param schemaNameSearch
     *            the schema name to use for search
     * @param columnNameOriginal
     *            the original column name
     * @param columnNameSearch
     *            the column name as it should be searched for (either the same
     *            as original, or lower case in case of case-insensitive search)
     * @return
     */
    private Column searchColumn(String schemaNameSearch, String columnNameOriginal, String columnNameSearch) {
        if (columnNameSearch.startsWith(schemaNameSearch)) {
            Schema schema = getSchemaByName(schemaNameSearch);
            if (schema != null) {
                String tableAndColumnPath = columnNameOriginal.substring(schemaNameSearch.length());

                if (tableAndColumnPath.charAt(0) == '.') {
                    tableAndColumnPath = tableAndColumnPath.substring(1);

                    Column column = getColumn(schema, tableAndColumnPath);
                    if (column != null) {
                        return column;
                    }
                }
            }
        }
        return null;
    }

    private final Column getColumn(final Schema schema, final String tableAndColumnPath) {
        Table table = null;
        String columnPath = tableAndColumnPath;
        final String[] tableNames = schema.getTableNames();
        for (final String tableName : tableNames) {
            if (tableName != null) {
                // search case-sensitive
                if (isStartingToken(tableName, tableAndColumnPath)) {
                    table = schema.getTableByName(tableName);
                    columnPath = tableAndColumnPath.substring(tableName.length());

                    if (columnPath.charAt(0) == '.') {
                        columnPath = columnPath.substring(1);
                        break;
                    }
                }
            }
        }

        if (table == null) {
            final String tableAndColumnPathInLowerCase = tableAndColumnPath.toLowerCase();
            for (final String tableName : tableNames) {
                if (tableName != null) {
                    String tableNameInLowerCase = tableName.toLowerCase();
                    // search case-insensitive
                    if (isStartingToken(tableNameInLowerCase, tableAndColumnPathInLowerCase)) {
                        table = schema.getTableByName(tableName);
                        columnPath = tableAndColumnPath.substring(tableName.length());

                        if (columnPath.charAt(0) == '.') {
                            columnPath = columnPath.substring(1);
                            break;
                        }
                    }
                }
            }
        }

        if (table == null && tableNames.length == 1) {
            table = schema.getTables()[0];
        }

        if (table != null) {
            Column column = table.getColumnByName(columnPath);
            if (column != null) {
                return column;
            }
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final Table getTableByQualifiedLabel(final String tableName) {
        if (tableName == null) {
            return null;
        }
        Schema schema = null;
        String[] schemaNames = getSchemaNames();
        for (String schemaName : schemaNames) {
            if (schemaName == null) {
                // there's an unnamed schema present.
                schema = getSchemaByName(null);
                if (schema != null) {
                    Table table = schema.getTableByName(tableName);
                    return table;
                }
            } else {
                // case-sensitive search
                if (isStartingToken(schemaName, tableName)) {
                    schema = getSchemaByName(schemaName);
                }
            }
        }

        if (schema == null) {
            final String tableNameInLowerCase = tableName.toLowerCase();
            for (final String schemaName : schemaNames) {
                if (schemaName != null) {
                    // case-insensitive search
                    final String schemaNameInLowerCase = schemaName.toLowerCase();
                    if (isStartingToken(schemaNameInLowerCase, tableNameInLowerCase)) {
                        schema = getSchemaByName(schemaName);
                    }
                }
            }
        }

        if (schema == null) {
            schema = getDefaultSchema();
        }

        String tablePart = tableName.toLowerCase();
        String schemaName = schema.getName();
        if (schemaName != null && isStartingToken(schemaName.toLowerCase(), tablePart)) {
            tablePart = tablePart.substring(schemaName.length());
            if (tablePart.startsWith(".")) {
                tablePart = tablePart.substring(1);
            }
        }

        return schema.getTableByName(tablePart);
    }

    private boolean isStartingToken(String partName, String fullName) {
        if (fullName.startsWith(partName)) {
            final int length = partName.length();
            if (length == 0) {
                return false;
            }
            if (fullName.length() > length) {
                final char nextChar = fullName.charAt(length);
                if (isQualifiedPathDelim(nextChar)) {
                    return true;
                }
            }
        }
        return false;
    }

    protected boolean isQualifiedPathDelim(char c) {
        return c == '.' || c == '"';
    }

    /**
     * Gets schema names from the non-abstract implementation. These schema
     * names will be cached except if the {@link #refreshSchemas()} method is
     * called.
     * 
     * @return an array of schema names.
     */
    protected abstract String[] getSchemaNamesInternal();

    /**
     * Gets the name of the default schema.
     * 
     * @return the default schema name.
     */
    protected abstract String getDefaultSchemaName();

    /**
     * Gets a specific schema from the non-abstract implementation. This schema
     * object will be cached except if the {@link #refreshSchemas()} method is
     * called.
     * 
     * @param name
     *            the name of the schema to get
     * @return a schema object representing the named schema, or null if no such
     *         schema exists.
     */
    protected abstract Schema getSchemaByNameInternal(String name);
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy