/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF 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 org.apache.metamodel.schema; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.metamodel.MetaModelHelper; import org.apache.metamodel.util.Action; import org.apache.metamodel.util.CollectionUtils; import org.apache.metamodel.util.HasNameMapper; import org.apache.metamodel.util.Predicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Abstract {@link Table} implementation. Includes most common/trivial methods. */ public abstract class AbstractTable implements Table { private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(AbstractTable.class); @Override public final int getColumnCount() { return getColumns().length; } @Override public Column getColumn(int index) throws IndexOutOfBoundsException { Column[] columns = getColumns(); return columns[index]; } @Override public final Column getColumnByName(final String columnName) { if (columnName == null) { return null; } final List<Column> foundColumns = new ArrayList<Column>(1); // Search for column matches, case insensitive. for (Column column : getColumns()) { final String candidateName = column.getName(); if (columnName.equalsIgnoreCase(candidateName)) { foundColumns.add(column); } } final int numColumns = foundColumns.size(); if (logger.isDebugEnabled()) { logger.debug("Found {} column(s) matching '{}': {}", new Object[] { numColumns, columnName, foundColumns }); } if (numColumns == 0) { return null; } else if (numColumns == 1) { // if there's only one, return it. return foundColumns.get(0); } // If more matches are found, search case sensitive for (Column column : foundColumns) { if (columnName.equals(column.getName())) { return column; } } // if none matches case sensitive, pick the first one. return foundColumns.get(0); } @Override public final int getRelationshipCount() { return getRelationships().length; } @Override public final Column[] getNumberColumns() { return CollectionUtils.filter(getColumns(), new Predicate<Column>() { @Override public Boolean eval(Column col) { ColumnType type = col.getType(); return type != null && type.isNumber(); } }).toArray(new Column[0]); } @Override public final Column[] getLiteralColumns() { return CollectionUtils.filter(getColumns(), new Predicate<Column>() { @Override public Boolean eval(Column col) { ColumnType type = col.getType(); return type != null && type.isLiteral(); } }).toArray(new Column[0]); } @Override public final Column[] getTimeBasedColumns() { return CollectionUtils.filter(getColumns(), new Predicate<Column>() { @Override public Boolean eval(Column col) { ColumnType type = col.getType(); return type != null && type.isTimeBased(); } }).toArray(new Column[0]); } @Override public final Column[] getBooleanColumns() { return CollectionUtils.filter(getColumns(), new Predicate<Column>() { @Override public Boolean eval(Column col) { ColumnType type = col.getType(); return type != null && type.isBoolean(); } }).toArray(new Column[0]); } @Override public final Column[] getIndexedColumns() { return CollectionUtils.filter(getColumns(), new Predicate<Column>() { @Override public Boolean eval(Column col) { return col.isIndexed(); } }).toArray(new Column[0]); } @Override public final Relationship[] getForeignKeyRelationships() { return CollectionUtils.filter(getRelationships(), new Predicate<Relationship>() { @Override public Boolean eval(Relationship arg) { return AbstractTable.this.equals(arg.getForeignTable()); } }).toArray(new Relationship[0]); } @Override public final Relationship[] getPrimaryKeyRelationships() { return CollectionUtils.filter(getRelationships(), new Predicate<Relationship>() { @Override public Boolean eval(Relationship arg) { return AbstractTable.this.equals(arg.getPrimaryTable()); } }).toArray(new Relationship[0]); } @Override public final Column[] getForeignKeys() { final Set<Column> columns = new HashSet<Column>(); final Relationship[] relationships = getForeignKeyRelationships(); CollectionUtils.forEach(relationships, new Action<Relationship>() { @Override public void run(Relationship arg) { Column[] foreignColumns = arg.getForeignColumns(); for (Column column : foreignColumns) { columns.add(column); } } }); return columns.toArray(new Column[columns.size()]); } @Override public final Column[] getPrimaryKeys() { final List<Column> primaryKeyColumns = new ArrayList<Column>(); final Column[] columnsInTable = getColumns(); for (Column column : columnsInTable) { if (column.isPrimaryKey()) { primaryKeyColumns.add(column); } } return primaryKeyColumns.toArray(new Column[primaryKeyColumns.size()]); } @Override public final String[] getColumnNames() { Column[] columns = getColumns(); return CollectionUtils.map(columns, new HasNameMapper()).toArray(new String[columns.length]); } @Override public final Column[] getColumnsOfType(ColumnType columnType) { Column[] columns = getColumns(); return MetaModelHelper.getColumnsByType(columns, columnType); } @Override public final Column[] getColumnsOfSuperType(final SuperColumnType superColumnType) { Column[] columns = getColumns(); return MetaModelHelper.getColumnsBySuperType(columns, superColumnType); } @Override public final Relationship[] getRelationships(final Table otherTable) { Relationship[] relationships = getRelationships(); return CollectionUtils.filter(relationships, new Predicate<Relationship>() { @Override public Boolean eval(Relationship relation) { if (relation.getForeignTable() == otherTable && relation.getPrimaryTable() == AbstractTable.this) { return true; } else if (relation.getForeignTable() == AbstractTable.this && relation.getPrimaryTable() == otherTable) { return true; } return false; } }).toArray(new Relationship[0]); } @Override public final String getQuotedName() { String quote = getQuote(); if (quote == null) { return getName(); } return quote + getName() + quote; } @Override public final String getQualifiedLabel() { StringBuilder sb = new StringBuilder(); Schema schema = getSchema(); if (schema != null && schema.getName() != null) { sb.append(schema.getQualifiedLabel()); sb.append('.'); } sb.append(getName()); return sb.toString(); } @Override public final String toString() { return "Table[name=" + getName() + ",type=" + getType() + ",remarks=" + getRemarks() + "]"; } @Override public int hashCode() { return getName().hashCode(); } @Override public boolean equals(final Object obj) { if (obj == null) { return false; } if (obj == this) { return true; } if (obj instanceof Table) { final Table other = (Table) obj; if (!getQualifiedLabel().equals(other.getQualifiedLabel())) { return false; } if (getType() != other.getType()) { return false; } final Schema sch1 = getSchema(); final Schema sch2 = other.getSchema(); if (sch1 != null) { if (!sch1.equals(sch2)) { return false; } } else { if (sch2 != null) { return false; } } try { final String[] columnNames1 = getColumnNames(); final String[] columnNames2 = other.getColumnNames(); if (columnNames1 != null && columnNames1.length != 0) { if (columnNames2 != null && columnNames2.length != 0) { if (!Arrays.equals(columnNames1, columnNames2)) { return false; } } } } catch (Exception e) { // going "down stream" may throw exceptions, e.g. due to // de-serialization issues. We will be tolerant to such // exceptions logger.debug("Caught (and ignoring) exception while comparing column names of tables", e); } return true; } return false; } @Override public final int compareTo(Table that) { int diff = getQualifiedLabel().compareTo(that.getQualifiedLabel()); if (diff == 0) { diff = toString().compareTo(that.toString()); } return diff; } }