net.hydromatic.optiq.jdbc.OptiqSchema.java Source code

Java tutorial

Introduction

Here is the source code for net.hydromatic.optiq.jdbc.OptiqSchema.java

Source

/*
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
package net.hydromatic.optiq.jdbc;

import net.hydromatic.linq4j.Linq4j;
import net.hydromatic.linq4j.expressions.Expression;

import net.hydromatic.optiq.*;
import net.hydromatic.optiq.Table;
import net.hydromatic.optiq.impl.MaterializedViewTable;
import net.hydromatic.optiq.util.Compatible;
import net.hydromatic.optiq.util.CompositeMap;

import org.eigenbase.util.Util;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.*;

import java.util.*;

/**
 * Schema.
 *
 * <p>Wrapper around user-defined schema used internally.</p>
 */
public class OptiqSchema {
    private final OptiqSchema parent;
    public final Schema schema;
    /** Tables explicitly defined in this schema. Does not include tables in
     *  {@link #schema}. */
    public final Map<String, TableEntry> tableMap = new HashMap<String, TableEntry>();
    private final Multimap<String, TableFunctionEntry> tableFunctionMap = LinkedListMultimap.create();
    private final Map<String, OptiqSchema> subSchemaMap = new HashMap<String, OptiqSchema>();
    public final Map<String, Table> compositeTableMap;
    public final Multimap<String, TableFunction> compositeTableFunctionMap;
    public final Map<String, OptiqSchema> compositeSubSchemaMap;

    public OptiqSchema(OptiqSchema parent, final Schema schema) {
        this.parent = parent;
        this.schema = schema;
        assert (parent == null) == (this instanceof OptiqRootSchema);
        this.compositeTableMap = CompositeMap.of(Maps.transformValues(tableMap, new Function<TableEntry, Table>() {
            public Table apply(TableEntry input) {
                return input.getTable();
            }
        }), Maps.transformValues(
                Multimaps.filterEntries(tableFunctionMap, new Predicate<Map.Entry<String, TableFunctionEntry>>() {
                    public boolean apply(Map.Entry<String, TableFunctionEntry> input) {
                        return input.getValue().getTableFunction().getParameters().isEmpty();
                    }
                }).asMap(), new Function<Collection<TableFunctionEntry>, Table>() {
                    public Table apply(Collection<TableFunctionEntry> input) {
                        // At most one function with zero parameters.
                        TableFunctionEntry entry = input.iterator().next();
                        return entry.getTableFunction().apply(ImmutableList.of());
                    }
                }), Compatible.INSTANCE.asMap(schema.getTableNames(), new Function<String, Table>() {
                    public Table apply(String input) {
                        return schema.getTable(input);
                    }
                }));
        // TODO: include schema's table functions in this map.
        this.compositeTableFunctionMap = Multimaps.transformValues(tableFunctionMap,
                new Function<TableFunctionEntry, TableFunction>() {
                    public TableFunction apply(TableFunctionEntry input) {
                        return input.getTableFunction();
                    }
                });
        this.compositeSubSchemaMap = CompositeMap.of(subSchemaMap, Compatible.INSTANCE
                .<String, OptiqSchema>asMap(schema.getSubSchemaNames(), new Function<String, OptiqSchema>() {
                    public OptiqSchema apply(String input) {
                        return addSchema(schema.getSubSchema(input));
                    }
                }));
    }

    /** Defines a table within this schema. */
    public TableEntry add(String tableName, Table table) {
        final TableEntryImpl entry = new TableEntryImpl(this, tableName, table);
        tableMap.put(tableName, entry);
        return entry;
    }

    private TableFunctionEntry add(String name, TableFunction tableFunction) {
        final TableFunctionEntryImpl entry = new TableFunctionEntryImpl(this, name, tableFunction);
        tableFunctionMap.put(name, entry);
        return entry;
    }

    public OptiqRootSchema root() {
        for (OptiqSchema schema = this;;) {
            if (schema.parent == null) {
                return (OptiqRootSchema) schema;
            }
            schema = schema.parent;
        }
    }

    public final OptiqSchema getSubSchema(String schemaName) {
        return subSchemaMap.get(schemaName);
    }

    /** Adds a child schema of this schema. */
    public OptiqSchema addSchema(Schema schema) {
        final OptiqSchema optiqSchema = new OptiqSchema(this, schema);
        subSchemaMap.put(schema.getName(), optiqSchema);
        return optiqSchema;
    }

    public String getName() {
        return schema.getName();
    }

    public void addTableFunction(TableFunctionEntry tableFunctionEntry) {
        throw Util.needToImplement(tableFunctionEntry);
    }

    public SchemaPlus plus() {
        return new SchemaPlusImpl();
    }

    public static OptiqSchema from(SchemaPlus plus) {
        return ((SchemaPlusImpl) plus).optiqSchema();
    }

    /**
     * Entry in a schema, such as a table or sub-schema.
     *
     * <p>Each object's name is a property of its membership in a schema;
     * therefore in principle it could belong to several schemas, or
     * even the same schema several times, with different names. In this
     * respect, it is like an inode in a Unix file system.</p>
     *
     * <p>The members of a schema must have unique names.
     */
    public abstract static class Entry {
        public final OptiqSchema schema;
        public final String name;

        public Entry(OptiqSchema schema, String name) {
            Linq4j.requireNonNull(schema);
            Linq4j.requireNonNull(name);
            this.schema = schema;
            this.name = name;
        }

        /** Returns this object's path. For example ["hr", "emps"]. */
        public final List<String> path() {
            return Schemas.path(schema.schema, name);
        }
    }

    /** Membership of a table in a schema. */
    public abstract static class TableEntry extends Entry {
        public TableEntry(OptiqSchema schema, String name) {
            super(schema, name);
        }

        public abstract Table getTable();
    }

    /** Membership of a table-function in a schema. */
    public abstract static class TableFunctionEntry extends Entry {
        public TableFunctionEntry(OptiqSchema schema, String name) {
            super(schema, name);
        }

        public abstract TableFunction getTableFunction();

        /** Whether this represents a materialized view. (At a given point in time,
         * it may or may not be materialized as a table.) */
        public abstract boolean isMaterialization();
    }

    /** Implementation of {@link SchemaPlus} based on an {@code OptiqSchema}. */
    private class SchemaPlusImpl implements SchemaPlus {
        public OptiqSchema optiqSchema() {
            return OptiqSchema.this;
        }

        public SchemaPlus getParentSchema() {
            return parent == null ? null : parent.plus();
        }

        public String getName() {
            return OptiqSchema.this.getName();
        }

        public boolean isMutable() {
            return schema.isMutable();
        }

        public Expression getExpression() {
            return schema.getExpression();
        }

        public Table getTable(String name) {
            return compositeTableMap.get(name);
        }

        public Set<String> getTableNames() {
            return compositeTableMap.keySet();
        }

        public Collection<TableFunction> getTableFunctions(String name) {
            return compositeTableFunctionMap.get(name);
        }

        public Set<String> getTableFunctionNames() {
            return compositeTableFunctionMap.keySet();
        }

        public SchemaPlus getSubSchema(String name) {
            final OptiqSchema subSchema = OptiqSchema.this.getSubSchema(name);
            return subSchema == null ? null : subSchema.plus();
        }

        public Set<String> getSubSchemaNames() {
            return subSchemaMap.keySet();
        }

        public SchemaPlus add(Schema schema) {
            final OptiqSchema optiqSchema = OptiqSchema.this.addSchema(schema);
            return optiqSchema.plus();
        }

        public SchemaPlus addRecursive(Schema schema) {
            return schema.getParentSchema().add(schema);
        }

        public <T> T unwrap(Class<T> clazz) {
            if (clazz.isInstance(this)) {
                return clazz.cast(this);
            }
            if (clazz.isInstance(OptiqSchema.this)) {
                return clazz.cast(OptiqSchema.this);
            }
            if (clazz.isInstance(OptiqSchema.this.schema)) {
                return clazz.cast(OptiqSchema.this.schema);
            }
            throw new ClassCastException("not a " + clazz);
        }

        public void add(String name, Table table) {
            OptiqSchema.this.add(name, table);
        }

        public void add(String name, TableFunction tableFunction) {
            OptiqSchema.this.add(name, tableFunction);
        }
    }

    /**
     * Implementation of {@link net.hydromatic.optiq.jdbc.OptiqSchema.TableEntry} where all properties are
     * held in fields.
     */
    public static class TableEntryImpl extends TableEntry {
        private final Table table;

        /** Creates a TableEntryImpl. */
        public TableEntryImpl(OptiqSchema schema, String name, Table table) {
            super(schema, name);
            assert table != null;
            this.table = table;
        }

        public Table getTable() {
            return table;
        }
    }

    /**
     * Implementation of {@link net.hydromatic.optiq.jdbc.OptiqSchema.TableFunctionEntry}
     * where all properties are held in fields.
     */
    public static class TableFunctionEntryImpl extends TableFunctionEntry {
        private final TableFunction tableFunction;

        /** Creates a TableFunctionEntryImpl. */
        public TableFunctionEntryImpl(OptiqSchema schema, String name, TableFunction tableFunction) {
            super(schema, name);
            this.tableFunction = tableFunction;
        }

        public TableFunction getTableFunction() {
            return tableFunction;
        }

        public boolean isMaterialization() {
            return tableFunction instanceof MaterializedViewTable.MaterializedViewTableFunction;
        }
    }
}

// End OptiqSchema.java