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

org.zodiac.fastorm.rdb.metadata.AbstractTableOrViewMetadata Maven / Gradle / Ivy

The newest version!
package org.zodiac.fastorm.rdb.metadata;

import org.zodiac.commons.util.lang.FastThreadLocalStringUtil;
import org.zodiac.fastorm.core.meta.Feature;
import org.zodiac.fastorm.core.meta.ObjectMetadata;
import org.zodiac.fastorm.rdb.metadata.dialect.Dialect;
import org.zodiac.fastorm.rdb.metadata.key.ForeignKeyBuilder;
import org.zodiac.fastorm.rdb.metadata.key.ForeignKeyMetadata;
import org.zodiac.fastorm.rdb.metadata.key.LazyForeignKeyMetadata;
import org.zodiac.fastorm.rdb.operator.builder.fragments.query.JoinFragmentBuilder;
import org.zodiac.fastorm.rdb.operator.builder.fragments.query.QueryTermsFragmentBuilder;
import org.zodiac.fastorm.rdb.operator.builder.fragments.query.SelectColumnFragmentBuilder;
import org.zodiac.fastorm.rdb.operator.builder.fragments.query.SortOrderFragmentBuilder;
import org.zodiac.fastorm.rdb.utils.FeatureUtils;
import org.zodiac.sdk.toolkit.util.ExceptionUtil;
import org.zodiac.sdk.toolkit.util.lang.ObjUtil;
import org.zodiac.sdk.toolkit.util.lang.StrUtil;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Abstract-table or view metadata.
 */
public abstract class AbstractTableOrViewMetadata implements TableOrViewMetadata {

    private String name;

    private String alias;

    private RDBSchemaMetadata schema;

    private String realName;

    private Consumer onColumnAdded;

    protected Map allColumns = new ConcurrentHashMap() {

        private static final long serialVersionUID = -2038243723808021090L;

        @Override
        public RDBColumnMetadata get(Object key) {
            String k = String.valueOf(key);
            RDBColumnMetadata metadata = super.get(k);
            if (metadata == null) {
                metadata = super.get(k.toUpperCase());
            }
            if (metadata == null) {
                metadata = super.get(k.toLowerCase());
            }
            return metadata;
        }
    };

    protected List columnView;

    protected List foreignKey = new CopyOnWriteArrayList<>();

    protected Map features = new ConcurrentHashMap<>();

    private String quoteName, fullName;

    public AbstractTableOrViewMetadata() {
        /*Register the default 'where' condition constructor.*/
        addFeature(QueryTermsFragmentBuilder.of(this));
        /*Register the default query column constructor.*/
        addFeature(SelectColumnFragmentBuilder.of(this));
        /*JOIN*/
        addFeature(JoinFragmentBuilder.of(this));
        /*ORDER*/
        addFeature(SortOrderFragmentBuilder.of(this));
    }

    public String getName() {
        return name;
    }

    public AbstractTableOrViewMetadata setName(String name) {
        this.name = name;
        return this;
    }

    public String getAlias() {
        return alias;
    }

    public AbstractTableOrViewMetadata setAlias(String alias) {
        this.alias = alias;
        return this;
    }

    public Map getAllColumns() {
        return allColumns;
    }

    public AbstractTableOrViewMetadata setAllColumns(Map allColumns) {
        this.allColumns = allColumns;
        return this;
    }

    public List getColumnView() {
        return columnView;
    }

    public AbstractTableOrViewMetadata setColumnView(List columnView) {
        this.columnView = columnView;
        return this;
    }

    public List getForeignKey() {
        return foreignKey;
    }

    public AbstractTableOrViewMetadata setForeignKey(List foreignKey) {
        this.foreignKey = foreignKey;
        return this;
    }

    public Map getFeatures() {
        return features;
    }

    public AbstractTableOrViewMetadata setFeatures(Map features) {
        this.features = features;
        return this;
    }

    public Consumer getOnColumnAdded() {
        return onColumnAdded;
    }

    public AbstractTableOrViewMetadata setSchema(RDBSchemaMetadata schema) {
        this.schema = schema;
        return this;
    }

    public AbstractTableOrViewMetadata setOnColumnAdded(Consumer onColumnAdded) {
        this.onColumnAdded = onColumnAdded;
        return this;
    }

    @Override
    public String getQuoteName() {
        if (quoteName == null) {
            return quoteName = (
                getSchema().getQuoteName()
                    + "."
                    + getDialect().quote(getRealName(), realName == null)
            );
        }
        return quoteName;
    }

    @Override
    public String getFullName() {
        if (fullName == null) {
            if (realName != null) {
                return fullName =
                    FastThreadLocalStringUtil.concat(getSchema().getQuoteName(), ".", getDialect().quote(getRealName(), false));
            }
            return fullName = FastThreadLocalStringUtil.concat(getSchema().getQuoteName(), ".", name);
        }
        return fullName;
    }

    public String getRealName() {
        return realName == null ? name : realName;
    }

    public AbstractTableOrViewMetadata setRealName(String realName) {
        this.realName = realName;
        this.quoteName = null;
        this.fullName = null;
        return this;
    }

    public boolean isTable() {
        return this instanceof RDBTableMetadata;
    }

    public boolean isView() {
        return this instanceof RDBViewMetadata;
    }

    public AbstractTableOrViewMetadata removeColumn(String name) {
        RDBColumnMetadata metadata = allColumns.remove(name);
        if (metadata != null) {
            allColumns.remove(metadata.getAlias());
        }
        return this;
    }

    @Override
    public RDBSchemaMetadata getSchema() {
        return schema;
    }

    public AbstractTableOrViewMetadata addColumn(RDBColumnMetadata column) {
        column.setOwner(this);
        allColumns.put(column.getName(), column);
        allColumns.put(column.getAlias(), column);
        allColumns.put(column.getRealName(),column);
        if (onColumnAdded != null) {
            onColumnAdded.accept(column);
        }
        return this;
    }

    @Override
    public List getColumns() {
        return new ArrayList<>(
            allColumns
                .values()
                .stream()
                .sorted()
                .collect(Collectors.toMap(RDBColumnMetadata::getName, Function.identity(), (_1, _2) -> _1, LinkedHashMap::new))
                .values());
    }

    @Override
    public List findColumns() {
        return allColumns
            .values()
            .stream()
            .flatMap(c -> getForeignKey()
                .stream()
                .map(ForeignKeyMetadata::getTarget)
                .map(TableOrViewMetadata::getColumns)
                .flatMap(Collection::stream))
            .sorted()
            .collect(Collectors.toList());
    }

    @Override
    public Optional getColumn(String name) {
        //if (StringUtils.isNullOrEmpty(name)) {
        if (ObjUtil.isEmpty(name)) {
            return Optional.empty();
        }
        return Optional.ofNullable(allColumns.get(StrUtil.getPlainName(name)));
    }

    @Override
    public Optional findColumn(String name) {
        return Optional.ofNullable(name)
            .map(this::getColumn)
            .filter(Optional::isPresent)
            .orElseGet(() -> findNestColumn(name));
    }

    @Override
    public void addForeignKey(ForeignKeyMetadata metadata) {
        foreignKey.add(metadata);
    }

    @Override
    public ForeignKeyMetadata addForeignKey(ForeignKeyBuilder builder) {
        ForeignKeyMetadata metadata = LazyForeignKeyMetadata.of(builder, this);
        addForeignKey(metadata);
        return metadata;
    }

    @Override
    public List getForeignKeys() {
        return new ArrayList<>(foreignKey);
    }

    @Override
    public Optional getForeignKey(String targetName) {
        return foreignKey
            .stream()
            .filter(key -> key.getTarget().equalsNameOrAlias(targetName) || key.equalsNameOrAlias(targetName))
            .findFirst();
    }

    @Override
    public void addFeature(Feature feature) {
        features.put(feature.getId(), feature);
    }

    @Override
    public Dialect getDialect() {
        return getSchema()
            .getDialect();
    }

    @Override
    public ObjectMetadata clone() {
        ObjectMetadata clone = null;
        try {
            clone = (ObjectMetadata) super.clone();
        } catch (CloneNotSupportedException e) {
            ExceptionUtil.chuck(e);
        }
        return clone;
    }

    public RDBColumnMetadata newColumn() {
        RDBColumnMetadata column = new RDBColumnMetadata();
        column.setSortIndex(getColumns().size() + 1);
        column.setOwner(this);
        return column;
    }

    @Override
    public void merge(TableOrViewMetadata metadata) {
        metadata.getForeignKeys().forEach(this::addForeignKey);
        for (Feature feature : metadata.getFeatureList()) {
            features.putIfAbsent(feature.getId(), feature);
        }
        metadata.getColumns().forEach(this::addColumn);
        if (metadata instanceof AbstractTableOrViewMetadata) {
            String relName = ((AbstractTableOrViewMetadata) metadata).realName;
            if (relName != null) {
                this.setRealName(relName);
            }
        }
    }

    @Override
    public void replace(TableOrViewMetadata metadata) {
        foreignKey.clear();
        features.clear();
        allColumns.clear();
        merge(metadata);
    }

    @Override
    public int hashCode() {
        return Objects.hash(alias, allColumns, columnView, features, foreignKey, fullName, name, onColumnAdded,
            quoteName, realName, schema);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        AbstractTableOrViewMetadata other = (AbstractTableOrViewMetadata)obj;
        return Objects.equals(alias, other.alias) && Objects.equals(allColumns, other.allColumns)
            && Objects.equals(columnView, other.columnView) && Objects.equals(features, other.features)
            && Objects.equals(foreignKey, other.foreignKey) && Objects.equals(fullName, other.fullName)
            && Objects.equals(name, other.name) && Objects.equals(onColumnAdded, other.onColumnAdded)
            && Objects.equals(quoteName, other.quoteName) && Objects.equals(realName, other.realName)
            && Objects.equals(schema, other.schema);
    }

    @Override
    public String toString() {
        return FeatureUtils.metadataToString(this);
    }

    private void setQuoteName(String quoteName) {
        this.quoteName = quoteName;
    }

    private void setFullName(String fullName) {
        this.fullName = fullName;
    }

    private Optional findNestColumn(String name) {
        if (name == null) {
            return Optional.empty();
        }

        if (name.contains(".")) {
            String[] arr = StrUtil.getPlainName(name.split("[.]"));
            if (arr.length == 2) {
                /*table.name*/

                return findColumnFromSchema(schema, arr[0], arr[1]);
            } else if (arr.length == 3) {
                /*schema.table.name*/

                return schema.getDatabase()
                             .getSchema(arr[0])
                             .flatMap(another -> findColumnFromSchema(another, arr[1], arr[2]));
            }
        }
        return Optional.empty();
    }

    private Optional findColumnFromSchema(RDBSchemaMetadata schema, String tableName, String column) {
        return Optional.of(schema.getTableOrView(tableName)
                        .flatMap(meta -> meta.getColumn(column)))
            .filter(Optional::isPresent)
            .orElseGet(() -> getForeignKey(tableName) /*Find information about foreign key associations.*/
                                                      .flatMap(key -> key.getTarget().getColumn(column)));
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy